答案1
和zsh
:
autoload -Uz zmv
mkdir -p {a..z} {A..Z}
zmv '[a-zA-Z]/(([a-zA-Z])*)' '$2/$1'
mv -- x/Xwhatever X/Xwhatever
将为每个文件运行,跳过mv
对已位于正确目录中的文件的调用。添加一个-n
选项以zmv
仅查看它将做什么而不实际执行它。
答案2
不如 优雅zmv
,但一个简单的for
-loop 就足够了:
#!/bin/bash
for letter in {a..z} {A..Z} ; do
mkdir /path/to/dest/$letter
mv /path/to/source/*/${letter}?* /path/to/dest/$letter
done
答案3
一个稍微高效的版本,仅遍历实际存在的字母和数字:
for file in *; do
if [[ ! -d "$file" ]]; then
firstLetter=${file:0:1}
mkdir -p "$firstLetter"
mv -- "$file" "$firstLetter"/
fi
done
但是,如果您有文件与目录之一同名。例如,名为 的文件a
不允许您创建也名为 的目录a
。为了解决这个问题,你可以这样做:
tmpDir=$(mktemp -p "." -d)
for file in *; do
if [[ ! -d "$file" ]]; then
firstLetter=${file:0:1};
## If a file exists with this name
if [[ -e "$firstLetter" && ! -d "$firstLetter" ]]; then
## move the file to the tmp dir and update the value
## of the $file variable to point to it
mv -- "$file" "$tmpDir"
file="$tmpDir/$file"
fi
mkdir -p "$firstLetter";
mv -- "$file" "$firstLetter"/;
fi
done
# $tmpDir should be empty by now
rmdir "$tmpDir"