在Linux中根据前缀编号将文件从文件夹移动到子文件夹

ubbxdtey  于 2022-11-28  发布在  Linux
关注(0)|答案(3)|浏览(358)

我对bash比较陌生,我已经尝试了这里可以找到的多种解决方案,但似乎没有一种适合我的情况。这很简单,我有一个文件夹,看起来像这样:

- images/
   - 0_image_1.jpg
   - 0_image_2.jpg
   - 0_image_3.jpg
   - 1_image_1.jpg
   - 1_image_2.jpg
   - 1_image_3.jpg

我想移动这些jpg文件到子文件夹的基础上的前缀号码,这样:

- images_0/
   - 0_image_1.jpg
   - 0_image_2.jpg
   - 0_image_3.jpg

- images_1/
   - 1_image_1.jpg
   - 1_image_2.jpg
   - 1_image_3.jpg

有没有一个bash命令可以用一种简单的方式来实现这一点?谢谢

e0uiprwp

e0uiprwp1#

for src in *_*.jpg; do
  dest=images_${src%%_*}/
  echo mkdir -p "$dest"
  echo mv -- "$src" "$dest"
done

如果输出正常,则删除两个echo.

8mmmxcuj

8mmmxcuj2#

我会用rename(也叫Perl rename)来实现这一点。它的功能非常强大,性能也非常好。下面是一个适合您的用例的命令:

rename --dry-run -p '$_="images_" . substr($_,0,1) . "/" . $_'  ?_*jpg

让我们仔细分析一下。在右端,我们指定我们只想处理以下划线前的单个字符/数字开头的文件,这样我们就不会在试图将命令应用于不适合的文件时造成损害。然后--dry-run意味着它实际上什么也不做,它只是向你展示它会做什么-这是一个非常有用的特性。然后是-p,它方便地表示 “在你去的时候为我创建任何必要的目录”。然后是命令的内容。它将当前文件名传递给一个名为$_的变量,然后我们需要创建一个名为$_的新变量来指定文件名。在本例中,我们只需要在images_后面加上现有文件名的第一个数字,然后再加上一个斜杠和原始文件名。简单!

输出示例

'0_image_1.jpg' would be renamed to 'images_0/0_image_1.jpg'
'0_image_2.jpg' would be renamed to 'images_0/0_image_2.jpg'
'1_image_3.jpg' would be renamed to 'images_1/1_image_3.jpg'

删除--dry-run,如果输出看起来不错,则再次真实的运行。
使用rename有几个好处:

  • 如果两个文件重命名为相同的内容,
  • 它可以跨目录重命名,在此过程中创建任何必要的中间目录,
  • 你可以先做一个预演来测试它
  • 您可以使用任意复杂的Perl代码来指定新名称。
    注意:在macOS上,您可以使用homebrew安装rename
brew install rename

:在某些1上,rename被称为Perl renameprename

2lpgd968

2lpgd9683#

What about this:

$ for file in $(ls images/*.jpg | cut -d/ -f2); do
        newdir="images_${file:0:1}"
        [[ ! -d  "$newdir" ]] && mkdir $newdir
        mv "images/$file" "$newdir"
done

Assuming the image filename has single digit prefix, newdir name is formed by appending a suffix of the first character of the filename ( ${file:0:1} - 0 is the offset and length is 1). And if directory newdir does not exist, create one. Finally, move file from old to new.
If the filename could have a multi-digit prefix like 10_image.jpg, use this:

for file in $(ls images/*.jpg | cut -d/ -f2); do
    newdir="images_$(echo $file | cut -d_ -f1)"
    [[ ! -d  "$newdir" ]] && mkdir "$newdir"
    mv "images/$file" "$newdir"
done

相关问题