1

Рассмотрим проблему, когда вы хотите переименовать файл с именем some/path/File With A Long Name.txt в some/path/File with a very long name.txt . Для меня это всегда была одна из немногих ситуаций, когда при работе с командной строкой не хватает удобства файловых браузеров на основе графического интерфейса, где вы можете просто "редактировать" имя файла вместо передачи как старого, так и нового имени до mv .

Как уже был дан ответ на этот вопрос, наиболее удобным решением на основе bash является использование фигурных скобок. Однако это все же не так удобно, как простое редактирование имени файла, особенно в ситуациях, когда у вас очень длинное имя файла с пробелами, и вы хотите изменить только несколько символов здесь и там.

У меня вопрос: есть ли способ переименовать файлы путем "редактирования" имени каким-либо образом внутри оболочки?

Отказ от ответственности: обратите внимание, что это вопрос с самостоятельным ответом. Я нашел решение, которое работает для меня, но я все еще открыт для любой альтернативной идеи.

5 ответов5

1

Я обычно возвращаюсь к завершению табуляции и редактированию readline. Тем не менее, вот переписывание bash вашего скрипта Python (требуется версия 4, я думаю, для модных опций read )

mvInPlace () {
    local path newpath
    for path in "$@"; do
        if [[ ! -f "$path" ]]; then
            echo "No such file: $path" >&2
            continue
        fi
        echo "Old path: $path"
        read -p "New path: " -i "$path" -e newpath
        mv -v "$path" "$newpath"
    done
}
1

Для zsh удобной комбинацией клавиш для дублирования предыдущего слова (в зависимости от режима zle) является Esc Ctrl _, это значение по умолчанию в режиме emacs . Вы можете (пере) определить это самостоятельно. например, просто Ctrl _, что хорошо в режиме vi :

bindkey "^_" copy-prev-word
bindkey "^_" copy-prev-shell-word   # respects shell quote/escape

С креплениями bash чтения строки по умолчанию вы можете правильно "редактировать" , а затем выполнить командную строку с Meta- X мета- E. Возможно, вы захотите установить EDITOR или VISUAL в предпочитаемый вами редактор, что, надеюсь, упростит задачу дублирования слова.

Вы можете почти, но не совсем использовать zsh copy-prev-word в bash, но его представление о том, что такое слово, не всегда делает вас счастливым (строго буквенно-цифровым):

bind "\C-_: copy-backward-word"

затем Ctrl _ Ctrl Y, чтобы вызвать.

Более новые версии bash (начиная с 4.0) поддерживают слова оболочки, но не для копирования, только для движения / удаления, поэтому небольшой взлом:

 bind "\C-_: shell-backward-kill-word"

Вы можете вырезать, а затем вставить (вернуть) слово назад дважды с двойным Ctrl Y.

Bash также позволяет вам связать функцию оболочки, и в этом случае вы можете делать творческие вещи, изменяя переменные READLINE_LINE и READLINE_POINT , но у меня пока нет такой функции для передачи. Вот игрушечная функция (минимум bash-4.3), которая либо дублирует последнее слово оболочки, либо, если последнее слово выглядит как команда sed применяет ее ко второму последнему слову оболочки и заменяет себя.

function _dupl() {
    [[ -z "${READLINE_LINE}" ]] && return                # empty, no action
    eval local -a aa=( "${READLINE_LINE}" ) 2>/dev/null  # split into words
    [[ ${#aa} -eq 0 ]] && return                         # parse problem

    if [[ "${aa[-1]:0:2}" == "s/" ]]; then               # sed 
        local _sed=$(sed -e "${aa[-1]}" <<< ${aa[-2]})
        unset aa[-1]                                     # remove last word
        printf -v READLINE_LINE "%q " "${aa[@]}"         # recreate line
        printf -v READLINE_LINE "%s%q" "${READLINE_LINE}" "$_sed"
    else
        printf -v READLINE_LINE "%s %q" "${READLINE_LINE}" "${aa[-1]}"
    fi
    READLINE_POINT=${#READLINE_LINE}   # move cursor to end
}
bind -x '"\C-_":"_dupl"'

Пример:

mv "some/path/File With A Long Name.txt" s/txt/bak/ Ctrl _

затем расширяется в строке ввода до:

mv some/path/File\ With\ A\ Long\ Name.txt some/path/File\ With\ A\ Long\ Name.bak

(вы заметите, что слова в кавычках становятся экранированными, поскольку printf %q используется для безопасного расширения)

Этот последний вариант, возможно, чрезмерно растягивает то, что можно считать "в оболочке". если у вас есть vim со netrw , вы можете просто отредактировать каталог как файл:

  • vim .
  • использовать обычные функции поиска / навигации
  • используйте R, чтобы переименовать файл / каталог в курсоре

Смотрите также: https://unix.stackexchange.com/questions/132235/quickest-way-to-rename-files-without-retyping-directory-path

0

Решение, которое я придумал, - это простой скрипт на Python, который опирается на функциональность модуля readline . Я использую это так: mvInPlace <PATH-TO-MOVE> . Сценарий теперь будет запрашивать новое имя / путь, который предварительно заполнен старым именем / путем. Модуль readline теперь предоставляет все возможности редактирования, например, вы можете даже переместить курсор с помощью сочетания клавиш CTRL + LEFT, чтобы перейти к следующему сегменту строки. Для подсказки данный путь преобразуется в абсолютный путь, что также облегчает перемещение чего-либо по другому пути.

#!/usr/bin/python

import os, sys, readline

if len(sys.argv) != 2:
  print "Usage: %s <PATH-TO-MOVE>" % os.path.basename(sys.argv[0])
  sys.exit(-1)

oldpath = os.path.abspath(sys.argv[1])
readline.set_startup_hook(lambda: readline.insert_text(oldpath))

print 'Old path: ' + oldpath
newpath = raw_input('New path: ')

cmd = 'mv -v "%s" "%s"' % (oldpath, newpath)
print "\n", cmd, "\n"
os.system(cmd)
0

Утилита rename очень полезна в таких ситуациях, как изменение регистра и так далее.

В противном случае я использую расширение табуляции для одноразовых правок:

mv File Вкладка File

будет производить:

mv File\ With\ A\ Long\ Name.txt File\ With\ A\ Long\ Name.txt который затем можно редактировать в командной строке по своему усмотрению .

0

Я всегда просто использую вкладку так:

имя файла здесь: тестовый файл с длинным name.txt

так в командной строке

вкладка ren test будет автоматически заполнять полное имя файла с помощью уже имеющихся здесь escape-символов, а затем нажимать пробел, чтобы я мог начать новое имя, и снова, просто введя тестовую вкладку, я снова получу то же имя файла с escape-символами

User@server:~/$ test\ file\ long\ name.txt test\ file\ long\ name.txt

и я могу либо просто отредактировать несколько нужных мне символов, либо, если я хочу изменить путь, я использую cp вместо ren и просто использовать <-, чтобы добраться до места и добавить любой новый путь, в который я хочу переместить файл. в * nix environs не имеет значения, как долго будет работать команда, вы можете редактировать любую ее часть до тех пор, пока вы не используете / или не переходите на новую строку, в любом случае она будет продолжать идти до бесконечности. Вы также можете отредактировать имя файла и ТОГДА добавить путь после возврата в пространство, если вы хотите не только изменить часть имени файла, но и изменить его на новый путь [конечно, вам нужен cp, а не ren и да, если вы измените имя файла, вы можете даже использовать cp в той же директории и даже не использовать ren вообще].

Я делаю все это без добавления чего-либо, поэтому, если вы настроены так делать, даже если вы подключаетесь к машине друзей, вам не хочется писать сценарии на лету или иначе забыть, как это сделать без сценария, когда необходимо.

Надеюсь, это поможет.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .