我在一个文件夹中有大约一百万个文件,格式为xxxx_description.jpg,其中xxx是一个从100到未知上限的数字。
列表与此类似:
146467_description1.jpg
146467_description2.jpg
146467_description3.jpg
146467_description4.jpg
14646_description1.jpg
14646_description2.jpg
14646_description3.jpg
146472_description1.jpg
146472_description2.jpg
146472_description3.jpg
146500_description1.jpg
146500_description2.jpg
146500_description3.jpg
146500_description4.jpg
146500_description5.jpg
146500_description6.jpg
要在文件夹中记下文件编号,我想将它们全部放入按开头编号分组的文件夹中。
即:
146467/146467_description1.jpg
146467/146467_description2.jpg
146467/146467_description3.jpg
146467/146467_description4.jpg
14646/14646_description1.jpg
14646/14646_description2.jpg
14646/14646_description3.jpg
146472/146472_description1.jpg
146472/146472_description2.jpg
146472/146472_description3.jpg
146500/146500_description1.jpg
146500/146500_description2.jpg
146500/146500_description3.jpg
146500/146500_description4.jpg
146500/146500_description5.jpg
146500/146500_description6.jpg
我正在考虑尝试使用命令行:find | awk {} | mv命令或写一个脚本,但我不知道如何最有效地做到这一点。
答案 0 :(得分:0)
您可以使用此脚本:
for i in [0-9]*_*.jpg; do
p=`echo "$i" | sed 's/^\([0-9]*\)_.*/\1/'`
mkdir -p "$p"
mv "$i" "$p"
done
答案 1 :(得分:0)
使用grep
for file in *.jpg;
do
dirName=$(echo $file | grep -oE '^[0-9]+')
[[ -d $dirName ]] || mkdir $dirName
mv $file $dirName
done
grep -oE '^[0-9]+'
将文件名中的起始数字提取为
146467
146467
146467
146467
14646
...
如果目录存在, [[ -d $dirName ]]
将返回1
[[ -d $dirName ]] || mkdir $dirName
确保mkdir
仅在测试[[ -d $dirName ]]
失败时才起作用,即导致该导致不存在
答案 2 :(得分:0)
如果你真的在处理数百万个文件,我怀疑一个glob(*.jpg
或[0-9]*_*.jpg
可能会失败,因为它会使shell的命令行太长。在这种情况下,您仍然可以使用find
。这样的事情可能有用:
find /path -name "[0-9]*_*.jpg" -exec sh -c 'f="{}"; mkdir -p "/target/${f%_*}"; mv "$f" "/target/${f%_*}/"' \;
为便于阅读而分手,这就是我们正在做的事情:
find /path
- 以/path
为起点运行查找-name "[0-9]*_*.jpg"
- 匹配所有目录中与此文件规范匹配的文件-exec sh -c
在每个文件上执行以下操作...
'f="{}";
- 将文件名放入变量...... mkdir -p "/target/${f%_*}";
- 根据该变量创建目标目录(阅读mkdir关于-p
选项的手册页)mv "$f" "/target/${f%_*}/"'
- 将文件移至目录。\;
- 结束-exec
表达式从好的方面来说,它可以处理find
可以处理的任意数量的文件(即仅受操作系统限制)。在不利方面,它为每个要处理的文件启动一个单独的shell。
请注意,上述答案适用于Bourne / POSIX / Bash 。如果您使用CSH或TCSH作为shell,则可能会出现以下情况:
#!/bin/tcsh
foreach f (*_*.jpg)
set split = ($f:as/_/ /)
mkdir -p "$split[1]"
mv "$f" "$split[1]/"
end
这假设filespec适合tcsh的glob缓冲区。我在一个命令行上测试了40000个文件(894KB),并且在FreeBSD中使用/ bin / sh或/ bin / csh没有问题。
就像上面的Bourne / POSIX / Bash参数扩展解决方案一样,这可以避免不必要的外部调用我没有测试过,并且即使速度较慢也会推荐find
解决方案。