[英]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.