递归重命名文件和目录

Naj*_*hin 6 find rename

我正在使用此命令重命名文件:

for fname in *;
do
    mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ')
done
Run Code Online (Sandbox Code Playgroud)

但它只在当前目录中重命名。假设我有很多目录,每个目录包含一些其他目录,最后一个目录树包含文件。我想用随机字符重命名它们。

我认为find . -type f应该可以工作,并且已经尝试过,但仍然没有得到任何工作命令。

Gil*_*il' 8

随着发现:

find . -type f -exec sh -c 'SHELL COMMAND' {} \;
Run Code Online (Sandbox Code Playgroud)

SHELL COMMAND依次调用每个找到的文件;文件名是"$0". 因此:

find . -type f -exec sh -c '
    mv "$0" "${0%/*}/$(printf "%s\n" "${0##*/}" | sha1sum | cut -d" " -f1)"
' {} \;
Run Code Online (Sandbox Code Playgroud)

(注意使用printf而不是echo,以防您有一个名为-e或的文件或-n其他一些有问题的情况echo。)

您可以通过批量调用 shell 来加快速度。

find . -type f -exec sh -c 'for x; do
      mv "$x" "${x%/*}/$(printf "%s\n" "${x##*/}" | sha1sum | cut -d" " -f1)";
    done' _ {} +
Run Code Online (Sandbox Code Playgroud)

在 zsh 中,有一种简单的方法可以递归地匹配当前目录及其子目录中的所有文件。该. 水珠预选赛限制匹配到正规文件,D包括点文件。

for x in **/*(.D); do mv …; done
Run Code Online (Sandbox Code Playgroud)

在 bash ?4 中,您可以运行shopt -s globstar和使用**/*递归匹配当前目录及其子目录中的所有文件。您需要在循环中过滤常规文件。

shopt -s globstar; GLOBIGNORE=".:.."
for x in **/*; do if [[ -f $x ]]; then mv …; done
Run Code Online (Sandbox Code Playgroud)


jas*_*yan 2

如果您使用的是 Bash 4+,您可以执行以下操作:

\n\n
#!/bin/bash\nshopt -s globstar\nfor fname in **/*; do \n  if [ -f "$fname" ]; then\n    mv ...\n  fi\ndone
Run Code Online (Sandbox Code Playgroud)\n\n

来自 Bash Hacker 的 Wiki:

\n\n
有一个新的 shell 选项 globstar。启用后,Bash 将在 ** \xe2\x80\x93 上执行递归通配,这意味着它匹配文件系统中当前位置的所有目录和文件,而不是仅匹配当前级别。
\n\n

http://wiki.bash-hackers.org/bash4

\n