我正在使用此命令来重命名文件:
for fname in *;
do
mv "$fname" $(echo "$fname" | sha1sum | cut -f1 -d' ')
done
但它只在当前目录中重命名。假设我有很多目录,每个目录都包含一些其他目录,最后一个目录树包含文件。我想用随机字符重命名它们。
我认为find . -type f
应该可以工作,并且已经尝试过,但仍然没有得到任何工作命令。
答案1
与查找:
find . -type f -exec sh -c 'SHELL COMMAND' {} \;
这会SHELL COMMAND
依次调用每个找到的文件;文件名是"$0"
.因此:
find . -type f -exec sh -c '
mv "$0" "${0%/*}/$(printf "%s\n" "${0##*/}" | sha1sum | cut -d" " -f1)"
' {} \;
(请注意使用printf
而不是echo
,以防您有一个名为-e
or的文件-n
或其他一些会echo
造成问题的情况。)
您可以通过批量调用 shell 来加快速度。
find . -type f -exec sh -c 'for x; do
mv "$x" "${x%/*}/$(printf "%s\n" "${x##*/}" | sha1sum | cut -d" " -f1)";
done' _ {} +
在 zsh 中,有一种简单的方法可以递归地匹配当前目录及其子目录中的所有文件。这.
全局限定符将匹配限制为常规文件,并D
包括点文件。
for x in **/*(.D); do mv …; done
在bash≥4中,可以递归运行shopt -s globstar
并使用**/*
来匹配当前目录及其子目录中的所有文件。您需要在循环中过滤常规文件。
shopt -s globstar; GLOBIGNORE=".:.."
for x in **/*; do if [[ -f $x ]]; then mv …; done
答案2
创建帮助程序脚本/tmp/tmp.sh:
#!/bin/bash
mv "$1" $(echo "$1" | sha1sum | cut -f1 -d' ')
使其可执行,然后调用它:
find . -type f -execdir /tmp/tmp.sh {} ";"
答案3
如果您使用的是 Bash 4+,您可以执行以下操作:
#!/bin/bash
shopt -s globstar
for fname in **/*; do
if [ -f "$fname" ]; then
mv ...
fi
done
来自 Bash Hacker 的 Wiki:
有一个新的 shell 选项 globstar。启用后,Bash 将在 ** 上执行递归通配符 - 这意味着它匹配文件系统中当前位置的所有目录和文件,而不是仅匹配当前级别。
答案4
这可以处理所有空白...
set -f; IFS=
while read -r -d $'\0' fname ;do
mv ...
done < <(find . -type f -name '*' -print0)
set +f; IFS=$' \t\n' # you don't have to reset unless it effects subsequent code