简体   繁体   English

BASH:查找并重命名文件和目录

[英]BASH: find and rename files & directories

I would like to replace :2f with a - in all file/dir names and for some reason the one-liner below is not working, is there any simpler way to achieve this? 我想在所有文件/目录名称中用-替换:2f ,并且由于某种原因,下面的一线无法正常工作,有没有更简单的方法来实现这一目标?

Directory name example: 目录名称示例:

AN :2f EXAMPLE

Command: 命令:

for i in $(find /tmp/ \( -iname ".*" -prune -o -iname "*:*" -print \)); do { mv $i $(echo $i | sed 's/\:2f/\-/pg'); }; done

You don't have to parse the output of find : 您不必解析find的输出:

find . -depth -name '*:2f*' -execdir bash -c 'echo mv "$0" "${0//:2f/-}"' {} \;

We're using -execdir so that the command is executed from within the directory containing the found file. 我们正在使用-execdir以便从包含找到的文件的目录中执行命令。 We're also using -depth so that the content of a directory is considered before the directory itself. 我们还使用-depth以便在目录本身之前先考虑目录的内容。 All this to avoid problems if the :2f string appears in a directory name. 如果目录名称中出现:2f字符串,所有这些都可以避免出现问题。

As is, this command is harmless and won't perform any renaming; 照原样,此命令是无害的,不会执行任何重命名。 it'll only show on the terminal what's going to be performed. 它只会在终端上显示将要执行的操作。 Remove echo if you're happy with what you see. 如果对看到的内容满意,请删除echo

This assumes you want to perform the renaming for all files and folders (recursively) in current directory. 假定您要对当前目录中的所有文件和文件夹(递归)执行重命名。

-execdir might not be available for your version of find , though. -execdir可能不适用于您的find版本。

If your find doesn't support -execdir , you can get along without as so: 如果您的find不支持-execdir ,那么您可以这样进行:

find . -depth -name '*:2f*' -exec bash -c 'dn=${0%/*} bn=${0##*/}; echo mv "$dn/$bn" "$dn/${bn//:2f/-}"' {} \;

Here, the trick is to separate the directory part from the filename part—that's what we store in dn (dirname) and bn (basename)—and then only change the :2f in the filename. 在这里,技巧是将目录部分与文件名部分分开(这就是我们存储在dn (目录名)和bn (基本名)中的内容),然后仅更改文件名中的:2f

Since you have filenames containing space, for will split these up into separate arguments when iterating. 由于文件名包含空格,因此for会在迭代时将它们分成单独的参数。 Pipe to a while loop instead: 用管道传递到while循环:

find /tmp/ \( -iname ".*" -prune -o -iname "*:*" -print \) | while read -r i; do
    mv "$i" "$(echo "$i" | sed 's/\:2f/\-/pg')"

Also quote all the variables and command substitutions. 同时引用所有变量和命令替换。

This will work as long as you don't have any filenames containing newline. 只要您没有任何包含换行符的文件名,它就可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM