【问题标题】:Copy files into folders based on regex matchs of file and folder names根据文件和文件夹名称的正则表达式匹配将文件复制到文件夹中
【发布时间】:2019-11-27 21:40:04
【问题描述】:

我有一种情况,我有一系列文件如下:

1234_A_data1_v1.ext
1234_A_data1_v2.ext
1234_A_data2_v1.ext
1234_A_data2_v2.ext
1234_B_data1_v1.ext
1234_B_data1_v2.ext
1234_B_data2_v1.ext
1234_B_data2_v2.ext
1234_AA_data1_v1.ext
1234_AA_data1_v2.ext
1234_AA_data2_v1.ext
1234_AA_data2_v2.ext
1234_BB_data1_v1.ext
1234_BB_data1_v2.ext
1234_BB_data2_v1.ext
1234_BB_data2_v2.ext

正则表达式字符串1234_[A-Z]+ 标识数据集。我想为每个这样的数据集创建文件夹(基于文件名),然后将相应的文件移动到所述文件夹中。例如,1234_A_data1_v1.ext、1234_A_data1_v2.ext、1234_A_data2_v1.ext、1234_A_data2_v2.ext 将放在文件夹 1234_A 下。

我设法创建了如下文件夹:

grep -o -E '^[0-9]+_[A-Z]+' seqnames | xargs echo | xargs mkdir

这给了我:

1234_A
1234_A_data1_v1.ext
1234_A_data1_v2.ext
1234_A_data2_v1.ext
1234_A_data2_v2.ext
1234_B
1234_B_data1_v1.ext
1234_B_data1_v2.ext
1234_B_data2_v1.ext
1234_B_data2_v2.ext
1234_AA
1234_AA_data1_v1.ext
1234_AA_data1_v2.ext
1234_AA_data2_v1.ext
1234_AA_data2_v2.ext
1234_BB
1234_BB_data1_v1.ext
1234_BB_data1_v2.ext
1234_BB_data2_v1.ext
1234_BB_data2_v2.ext

这一切都很好。但是现在,我不知道如何将文件移动到各自的文件夹中,我很迷茫。

任何关于我如何实现这一点的指针将不胜感激。

特别是,有什么方法可以做类似mv *<pattern>*filename *<pattern>*destination 的事情吗?我也有兴趣了解是否有其他简洁(也许是正确的?)方法来完成这项任务。

【问题讨论】:

    标签: regex bash shell unix mv


    【解决方案1】:

    好吧,如果所有这些文件都遵循您显示的模式并且位于同一目录中,那么这种单行似乎可以工作。

    $ for d in $( cut -f1-2 -d_ <(ls 1234_*) | sort -u ); do mkdir $d; mv ${d}_* $d; done
    

    此 bash 命令使用 Looping ConstructforPipeline|Process Substitution&lt;(...)Command Substitution$(...)

    ls 1234_* 创建与该模式匹配的所有文件的列表。 cut -f1-2 -d__ 上拆分每个匹配的文件名,然后仅输出前两个字段(包括这两个字段之间的分隔符_)。 sort -u 首先对这些 cut 前缀进行排序,然后仅输出唯一项。您要为目录名称使用的正是这些唯一前缀。 for 然后遍历这些唯一前缀创建目录 (mkdir) 和 mv 将前缀匹配文件添加到该新目录。

    谨慎使用并根据需要进行调整。如果此目录中还有其他文件或目录,或者在执行命令时出现错误,执行或重新执行命令可能不会执行您想要的操作,因为会创建目录,glob 将不匹配你想要什么,等等。

    这是一个例子。

    $ ls -alF   # Show the files in the directory
    total 8
    drwxrwxr-x.  2 user user 4096 Jul 19 02:15 ./
    drwxrwxr-x. 34 user user 4096 Jul 19 02:02 ../
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_AA_data1_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_AA_data1_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_AA_data2_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_AA_data2_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_A_data1_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_A_data1_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_A_data2_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_A_data2_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_BB_data1_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_BB_data1_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_BB_data2_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_BB_data2_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_B_data1_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_B_data1_v2.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_B_data2_v1.ext
    -rw-rw-r--.  1 user user    0 Jul 19 02:07 1234_B_data2_v2.ext
    $ for d in $( cut -f1-2 -d_ <(ls 1234_*) | sort -u ); do mkdir $d; mv ${d}_* $d; done  # the one-liner
    $ ls -alF  # show the directory now
    total 24
    drwxrwxr-x.  6 user user 4096 Jul 19 02:17 ./
    drwxrwxr-x. 34 user user 4096 Jul 19 02:02 ../
    drwxrwxr-x.  2 user user 4096 Jul 19 02:17 1234_A/
    drwxrwxr-x.  2 user user 4096 Jul 19 02:17 1234_AA/
    drwxrwxr-x.  2 user user 4096 Jul 19 02:17 1234_B/
    drwxrwxr-x.  2 user user 4096 Jul 19 02:17 1234_BB/
    $ tree .  # show the whole directory tree structure
    .
    ├── 1234_A
    │   ├── 1234_A_data1_v1.ext
    │   ├── 1234_A_data1_v2.ext
    │   ├── 1234_A_data2_v1.ext
    │   └── 1234_A_data2_v2.ext
    ├── 1234_AA
    │   ├── 1234_AA_data1_v1.ext
    │   ├── 1234_AA_data1_v2.ext
    │   ├── 1234_AA_data2_v1.ext
    │   └── 1234_AA_data2_v2.ext
    ├── 1234_B
    │   ├── 1234_B_data1_v1.ext
    │   ├── 1234_B_data1_v2.ext
    │   ├── 1234_B_data2_v1.ext
    │   └── 1234_B_data2_v2.ext
    └── 1234_BB
        ├── 1234_BB_data1_v1.ext
        ├── 1234_BB_data1_v2.ext
        ├── 1234_BB_data2_v1.ext
        └── 1234_BB_data2_v2.ext
    
    4 directories, 16 files
    

    【讨论】:

    • 感谢您的回答。这非常有效。你能解释一下为什么你在那里使用sort 来创建循环列表吗?
    • @Dunois 我在答案中增加了单行描述。请注意,这只是执行此操作的众多方法之一,可能不是“最好的”,但我相信可以以这种方式组织许多文件。