2012-04-16 38 views
0

我的问题是我在单个目录中有太多文件。我不能“ls”这个目录,cos太大。我需要移动更好的目录结构中的所有文件。如何在多个不同目录中移动多个文件(在Linux上)

我以相反方式使用来自ID的最后3位数字作为文件夹。

例如ID 2018972必须在/2/7/9/img_2018972.jpg去。

我已经创建了目录,但现在我需要帮助bash脚本。我知道这些ID,范围1,300,000 - 2,000,000。但我无法处理正则表达式。

我wan't将所有的文件是这样的:

/images/folder/img_2018972.jpg -> /images/2/7/9/img_2018972.jpg 

我会很高兴在这个问题上的任何帮助。谢谢!

+0

你可以使用类似的东西来模拟'ls'; '为f in *;做printf - “%s \ t”“$ f”;完成'和'ls -1'与'for f in *;做printf - “%s \ n”“$ f”;完成'。 'ls'因为'ARG_MAX',最大参数限制而失败。 – c00kiemon5ter 2012-04-16 10:47:48

+0

感谢重播,我忘了提及,在文件夹中我有更多的jpg文件具有相同的文件名结构,但在结尾处有“_220,_380”..如:img_1234567_220.jpg。 – Alex 2012-04-16 11:00:00

+0

你的意思是说你不想匹配那些?或者答案没问题? – c00kiemon5ter 2012-04-16 11:03:41

回答

1

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

  • 文件名是在img_<id>.jpgimg_<id>_<size>.jpg
  • 形式新的目录是反向顺序的最后三个数字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 

如果*不能处理它(虽然我觉得*在for循环中没有限制),
使用find作为意见提出由@米哈尔Kosmulski

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") 
+0

由于文件数量庞大,'/ images/folder/*。jpg'的shell扩展可能无法工作,但是您可以用'find/images/folder -maxdepth 1 -type f -name替换for循环'* .jpg'|同时阅读;做<根据$ REPLY>做东西;完成' – 2012-04-16 10:34:39

+0

添加了该选项,但我认为'*'在循环中使用时没有限制。当用作函数/脚本的参数时有限制;那是'ARG_MAX'。 – c00kiemon5ter 2012-04-16 10:42:58

+0

感谢您的帮助。我使用了脚本的第二个版本(我们在评论中使用了@MichałKosmulski的建议)。它工作的很好,即使在文件夹中他们是如此多的文件,我甚至不能算......我想有超过2-3百万个文件。让我们看看它何时完成。感谢大家的帮助! – Alex 2012-04-16 12:25:24

0
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 
+0

我认为这是计算偏移量过多的工作。在UNIX和UNIX等操作系统中,也允许文件名包含任何内容。你最好在那里添加一些引号,并查看'-r'开关到'read'。尝试在你的shell中“帮助阅读”;) – c00kiemon5ter 2012-04-16 10:52:00

相关问题