Regex 如何移动多个不同目录中的多个文件(在Linux上)

Regex 如何移动多个不同目录中的多个文件(在Linux上),regex,linux,file,bash,shell,Regex,Linux,File,Bash,Shell,我的问题是在一个目录中有太多的文件。我无法“ls”该目录,因为它太大了。我需要在更好的目录结构中移动所有文件 我将ID中的最后3位数字作为文件夹反向使用 例如,ID2018972必须进入/2/7/9/img\u 2018972.jpg 我已经创建了目录,但现在需要bash脚本的帮助。我知道ID,范围在1300000到2000000之间。但是我不能处理正则表达式 我不想像这样移动所有文件: /images/folder/img_2018972.jpg -> /images/2/7/9/img

我的问题是在一个目录中有太多的文件。我无法“
ls
”该目录,因为它太大了。我需要在更好的目录结构中移动所有文件

我将ID中的最后3位数字作为文件夹反向使用

例如,ID
2018972
必须进入
/2/7/9/img\u 2018972.jpg

我已经创建了目录,但现在需要bash脚本的帮助。我知道ID,范围在1300000到2000000之间。但是我不能处理正则表达式

我不想像这样移动所有文件:

/images/folder/img_2018972.jpg -> /images/2/7/9/img_2018972.jpg
我将非常感谢在这个问题上的任何帮助。谢谢

编辑:在注释中解释后,存在以下假设:

  • 文件名的格式为
    img\uuu0.jpg
    img\uuu0.jpg
  • 新的dir是id的最后三位数字的倒序
使用Bash:

for file in /images/folder/*.jpg; do 
    fname="${file%.*}"      # remove extension and _<size>
    [[ "$fname" =~ img_[0-9]+_[0-9]+$ ]] && fname="${fname%_*}"

    last0="${fname: -1:1}"  # last letter/digit
    last1="${fname: -2:1}"  # last but one letter/digit
    last2="${fname: -3:1}"  # last but two letter/digit

    newdir="/images/$last0/$last1/$last2"
    # optionally check if the new dir exists, if not create it
    [[ -d "$newdir" ]] || mkdir -p "$newdir"

    mv "$file" "$newdir"
done

由于文件数量巨大,
/images/folder/*.jpg
的shell扩展可能无法工作,但您可以在读取时用
find/images/folder-maxdepth 1-type f-name'*.jpg'|替换for循环;做done
添加了该选项,尽管我认为
*
在循环中使用时没有限制。当用作函数/脚本的参数时存在限制<代码>ARG_MAX就是这样。感谢您的大力帮助。我使用了脚本的第二个版本(我们在评论中使用@MichałKosmulski建议的find)。它的工作非常好,即使在文件夹中,他们有这么多的文件,我甚至无法计数。。。我想超过200-300万个文件。让我们看看它什么时候完成。谢谢大家的帮助!您可以使用以下内容模拟
ls
<代码>用于f in*;执行printf--%s\t“$f”;完成和
ls-1
对f in*;执行printf--%s\n“$f”;完成
ls
在这里失败,因为
ARG\u MAX
,最大参数限制。感谢您的重播,我忘了提到,在文件夹中我有更多具有相同文件名结构的jpg文件,但末尾有“\u 220,\u 380”。。比如:img_1234567_220.jpg。你的意思是你不想匹配这些吗?或者答案正确吗?我也想匹配它们,只是我不确定答案是否正确。我可以为任何图像大小制作几个bash脚本,因为它们不只是两个。。事实上,它们是(_80,_125,_220,_340,_380,_620)。我会使用你的解决方案,但你能告诉我它安全吗?:)使用@kev的答案,任何以三位数字结尾并后跟
.jpg
的文件名都将匹配。在我的回答中,任何以
.jpg
结尾的文件名都将被匹配,最后三个字母将被提取。kev将不匹配_80,并且不会移动这些文件(因为“_”不是数字/在0-9范围内),而我的将匹配它,并将其移动到
/images/0/8/
。如果不需要的话,我可以改变这种行为。我认为计算偏移量的工作量太大了。在UNIX和类似UNIX的操作系统中,文件名也可以包含任何内容。您最好在那里添加一些引号,然后查找
-r
开关,切换到
read
。尝试在shell中阅读帮助
while read -r; do 
    fname="${REPLY%.*}"     # remove extension and _<size>
    [[ "$fname" =~ img_[0-9]+_[0-9]+$ ]] && fname="${fname%_*}"

    last0="${fname: -1:1}"  # last letter/digit
    last1="${fname: -2:1}"  # last but one letter/digit
    last2="${fname: -3:1}"  # last but two letter/digit

    newdir="/images/$last0/$last1/$last2"
    # optionally check if the new dir exists, if not create it
    [[ -d "$newdir" ]] || mkdir -p "$newdir"

    mv "$REPLY" "$newdir"
done < <(find /images/folder/ -maxdepth 1 -type f -name "*.jpg")
find /images/folder -type f -maxdepth 1 | while read file
do
filelen=${#file}
((rootn=$filelen-5))
((midn=$filelen-6))
((topn=$filelen-7))
root=${file:$rootn:1}
mid=${file:$midn:1}
top=${file:$topn:1}
mkdir -p /images/${root}/${mid}/${top}
mv $file /images/${root}/${mid}/${top}
done