我怎样才能通过在 shell 中简单地“编辑”文件路径来重命名/移动文件?

我怎样才能通过在 shell 中简单地“编辑”文件路径来重命名/移动文件?

some/path/File With A Long Name.txt考虑一下您想要重命名文件的问题some/path/File with a very long name.txt。对我来说,这始终是少数几种情况之一,使用命令行缺乏基于 GUI 的文件浏览器的便利性,在 GUI 中,您可以简单地“编辑”文件的名称,而不必将旧名称和新名称都传递给mv

正如已经回答的那样这个问题,最方便的基于 bash 的解决方案是使用括号扩展。然而,这仍然不如简单地编辑文件名那么方便,特别是在文件名很长且带有空格而您只想更改其中几个字符的情况下。

我的问题是:有没有办法通过在 shell 中以某种方式“编辑”名称来重命名文件?

免责声明:请注意,这是一个自答问题。我想出了一个适合自己的解决方案,但我仍然愿意接受任何其他想法。

答案1

我通常会使用 tab 补全和 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
}

答案2

zsh一个方便的快捷方式可以复制上一个单词(取决于你的 zle 模式)EscCtrl _ ,这是默认的emacs模式。你可以自己(重新)定义它。例如,Ctrl_模式:

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

使用默认的readline 绑定,您可以正确“编辑”然后使用 Meta- Meta-bash执行命令行。您可能希望将或变量设置为您喜欢的编辑器,这有望使复制单词的任务变得更容易。XEEDITORVISUAL

您几乎可以但不能完全在 bash 中使用 zsh copy-prev-word,但它对于单词的概念并不总是让您满意(严格来说是字母数字):

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

然后Ctrl _ CtrlY调用。

较新的 bash 版本(自 4.0 开始)支持 shell 语句,但不支持复制,只支持移动/删除,因此一个简单的 hack 方法是:

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

然后,您可以剪切,然后使用双击将单词粘贴(拉)两次CtrlY

Bash 还允许您绑定 shell 函数,在这种情况下,您可以通过更改变量READLINE_LINE和来做一些创造性的事情READLINE_POINT但我现在手头没有这样的函数。这是一个玩具函数(最低 bash-4.3),它可以复制最后一个 shell 单词,或者如果最后一个单词似乎是命令,sed则将其应用于倒数第二个 shell 单词并替换自身。

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用于安全扩展)

最后一个选项可能过度延伸了人们所认为的“在 shell 中”的功能。如果您有vimnetrw脚本,您可以简单地将目录作为文件进行编辑:

  • vim .
  • 使用正常搜索/导航功能
  • 用于R重命名光标处的文件/目录

也可以看看:https://unix.stackexchange.com/questions/132235/quickest-way-to-rename-files-without-retyping-directory-path

答案3

rename实用程序在更改大小写等情况下非常有用。

否则,我使用制表符扩展进行一次性编辑:

mv File Tab File Tab

将产生:

mv File\ With\ A\ Long\ Name.txt File\ With\ A\ Long\ Name.txt然后您可以根据需要在命令行上进行编辑。

答案4

我总是像这样使用 tab:

文件名在此处:测试文件长名.txt

所以在命令行上

ren testtab会自动填写完整的文件名,其中已经有转义字符,然后点击,space这样我就可以开始输入新的名字,再次输入 testtab就会给我一个带有转义字符的相同文件名,所以现在

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

我可以只编辑我需要的几个字符,如果我想更改路径,我可以使用 cp 而不是 ren,然后使用它<-来进入该空间并添加我想将文件移动到的新路径。在 *nix 环境中,命令有多长并不重要,您都可以编辑它的任何部分,只要您不使用 / 或跳转到新行,它就会一直无限下去。如果您不仅想更改文件的某些名称,还想将其更改为新路径,您还可以编辑文件名,然后在移回该空间后添加路径[当然您需要 cp 而不是 ren,是的,如果您更改文件的名称,您甚至可以在同一目录中使用 cp 而根本不使用 ren]。

我所做的一切都没有添加任何东西,所以如果你适应了这种方式,即使你拉到朋友的机器上,你也不会试图即时编写脚本,或者在需要时忘记如何在没有脚本的情况下执行操作。

希望有所帮助。

相关内容