BASH 使用 for、mv 和 grep 对大量文件按字母顺序排序
BASH one-line alphabetical mass file sort using for, mv, and grep
问题
我有数千个格式为 "^[[:digit:]]\{4\} - [[:alpha:]].*"
的文件,例如:7958 - a3ykof zyimeo3.txt。我试图简单地将它们按字母顺序移动到文件夹中,从连字符后的第一个字母字符开始。
我觉得我已经很接近按照我想要的方式实现它了,但是有一个(希望很简单)问题。
我先用 echo 测试了命令,以确保它获取了正确的信息。然后我尝试用 mv 真正执行它。我根据此文件列表在下面包含了一些示例:
1439 - a74389 josifj3oj.txt
3589 - Bfoei 839982 3il.txt
4719 - an38n8f n839mm20 mi02.txt
6398 - b39ji oij3o8 j2o.txt
9287 - A2984 j289jj9 oiw.txt
.... several thousand more files
例子
这有效
这列出了所有以字母 "a" 开头的文件(在开头的 4 位数字-space-连字符-space 模式之后):
for i in "$(ls | grep -i "^[[:digit:]]\{4\} - a")"; do echo "$i"; done
这失败了
这不会将所有以字母 "a" 开头的文件(在 4 位数字-space-连字符-space 模式之后)放入 "A"文件夹:
for i in "$(ls | grep -i "^[[:digit:]]\{4\} - a")"; do mv "$i" A; done
我希望第二个命令将名为“#### - a*”或“#### - A*”的每个文件移动到名为 A 的文件夹中。但它认为它是一个大文件 string/filename 加入 "\n".
这是一个示例错误消息:
mv: cannot stat '1439 - a74389 josifj3oj.txt\n9287 - A2984 j289jj9 oiw.txt\n2719 - an38n8f n839mm20 mi02.txt': No such file or directory
有人知道我错过了什么吗?
编辑
在@alvits 的回答与@chepner 和@courtlandj 的评论之间,对我来说完美无缺的是:
for directory in {A..Z}; do
mkdir -p "$directory" &&
find . -iregex "./[0-9]* - ${directory}.*" -exec mv -t "$directory" {} +;
done
这是最简单的方法。
for directory in {A..Z}; do
mkdir "$directory" &&
find . -iregex "./[0-9]* - ${directory}.*" -exec mv "{}" "$directory" \;
done
for
循环将根据文件所属的每个目录查询文件名。
find
命令将找到文件并将它们移动到目录。
BASH 具有类似 RE 的通配符和内置的序列创建功能。您可以像这样使用它:
for i in {{A..Z},{a..z}}; do
mkdir "${i}" && mv [0-9][0-9][0-9][0-9]" - ${i}"*" "${i}"
done
你注意到数字的四次重复,是的,它看起来比像 [0-9]{4}
这样的普通 RE 笨拙。
问题
我有数千个格式为 "^[[:digit:]]\{4\} - [[:alpha:]].*"
的文件,例如:7958 - a3ykof zyimeo3.txt。我试图简单地将它们按字母顺序移动到文件夹中,从连字符后的第一个字母字符开始。
我觉得我已经很接近按照我想要的方式实现它了,但是有一个(希望很简单)问题。
我先用 echo 测试了命令,以确保它获取了正确的信息。然后我尝试用 mv 真正执行它。我根据此文件列表在下面包含了一些示例:
1439 - a74389 josifj3oj.txt
3589 - Bfoei 839982 3il.txt
4719 - an38n8f n839mm20 mi02.txt
6398 - b39ji oij3o8 j2o.txt
9287 - A2984 j289jj9 oiw.txt
.... several thousand more files
例子
这有效
这列出了所有以字母 "a" 开头的文件(在开头的 4 位数字-space-连字符-space 模式之后):
for i in "$(ls | grep -i "^[[:digit:]]\{4\} - a")"; do echo "$i"; done
这失败了
这不会将所有以字母 "a" 开头的文件(在 4 位数字-space-连字符-space 模式之后)放入 "A"文件夹:
for i in "$(ls | grep -i "^[[:digit:]]\{4\} - a")"; do mv "$i" A; done
我希望第二个命令将名为“#### - a*”或“#### - A*”的每个文件移动到名为 A 的文件夹中。但它认为它是一个大文件 string/filename 加入 "\n".
这是一个示例错误消息:
mv: cannot stat '1439 - a74389 josifj3oj.txt\n9287 - A2984 j289jj9 oiw.txt\n2719 - an38n8f n839mm20 mi02.txt': No such file or directory
有人知道我错过了什么吗?
编辑
在@alvits 的回答与@chepner 和@courtlandj 的评论之间,对我来说完美无缺的是:
for directory in {A..Z}; do
mkdir -p "$directory" &&
find . -iregex "./[0-9]* - ${directory}.*" -exec mv -t "$directory" {} +;
done
这是最简单的方法。
for directory in {A..Z}; do
mkdir "$directory" &&
find . -iregex "./[0-9]* - ${directory}.*" -exec mv "{}" "$directory" \;
done
for
循环将根据文件所属的每个目录查询文件名。
find
命令将找到文件并将它们移动到目录。
BASH 具有类似 RE 的通配符和内置的序列创建功能。您可以像这样使用它:
for i in {{A..Z},{a..z}}; do
mkdir "${i}" && mv [0-9][0-9][0-9][0-9]" - ${i}"*" "${i}"
done
你注意到数字的四次重复,是的,它看起来比像 [0-9]{4}
这样的普通 RE 笨拙。