在子文件夹中查找具有给定扩展名的所有文件,并添加与子文件夹对应的子字符串

在子文件夹中查找具有给定扩展名的所有文件,并添加与子文件夹对应的子字符串

我有许多txt文件,分散在不同的文件夹中。

- case1
   |
    - 0.25
       |
        - case1.txt
    - 0.35
       |
        _ case1.txt
    - 0.30
       |
        _ case1.txt
    - 0.45
       |
        _ case1.txt

- case2
   |
    - 0.25
       |
        - case2.txt
    - 0.35
       |
        _ case2.txt
    - 0.30
       |
        _ case2.txt
    - 0.45
       |
        _ case2.txt

.
.
.

我想将它们全部复制到一个文件夹中,但不幸的是,正如您所见,其中一些文件具有相同的名称,因此一个简单的find解决方案最终会覆盖它们。我想将所有文件复制txt到一个目录foo,并在扩展名之前插入它们所在子文件夹的名称.txt。此外,由于子文件夹名称中有一个点,并且我需要将这些文件复制到 Windows,所以我还想更改0.250_25。换句话说,文件

- case2
   |
    - 0.25
       |
        - case2.txt

必须复制到fooas case2_0_25.txt。如果 bash 解决方案太复杂/难以理解,Python 解决方案也可以,但是不是一个 zsh 。

答案1

将副本分为两个转换,第一步将点和斜线转换为下划线,下一步将匹配的子表达式重新排列为所需的顺序。

shopt -s globstar; \
tar -cvf - --show-transformed-names --transform='s![.]!_!g' --transform='s!.*/\([^/]\+\)/\([^/]\+\)_txt$!foo/\2_\1.txt!' case*/**/*.txt | tar -xf -

现在,匹配至关重要--transform,否则这些文件将无法得到处理。

Bash 解决方案的工作方式大致相同。

#!/bin/bash

shopt -s nullglob globstar

mkdir -p foo
while read -rd ''; do
    [[ ${REPLY//./_} =~ ([^/]+)/([^/]+)_txt$ ]] && 
        cp -va "$REPLY" "foo/${BASH_REMATCH[2]}_${BASH_REMATCH[1]}.txt"
done < <(printf %s\\0 case*/**/*.txt)

答案2

您可以使用 bash 的 globstar 选项轻松地完成此操作(来自man bash):

全球星

如果设置,路径名扩展上下文中使用的模式**将匹配所有文件和零个或多个目录和子目录。如果模式后跟/,则仅匹配目录和子目录。

因为我们可以用来**查找文件,所以我们只需要将新名称定义为包含原始目录名称并更改._

for file in **/*.txt; do 
    newName=$(sed 's|[/.]|_|g' <<<"$file" | sed 's/_txt$/.txt/')
    cp -- "$file" foo/"$newName" 
done

解释

  • for file in **/*.txt; do:查找当前目录中名称以 结尾的所有文件(和目录,如果相关)*.txt
  • newName=$(sed 's|[/.]|_|g' <<<"$file" | sed 's/_txt$/.txt/'):使用将所有和sed转换为文件名中的 。请注意,这里还包括路径,因此它将类似于, 变成。然后,我们将第一个的输出传递给第二个,它将转换(如果在行尾找到)为,得到“case1_0_25_case1.txt $newName”。/._$filecase1/0.25/case1.txtcase1_0_25_case1_txtsed_txt.txt. The final output is saved in the variable
  • cp -- "$file" foo/"$newName":我们现在将文件复制到目录foo/并使用新名称。--这里实际上不需要,但可以确保该方法适用于任何文件名,包括名称以 开头的文件名-

我重新创建了您在问题中显示的文件夹结构,运行了上述命令并得到:


$ tree
.
├── case1
│   ├── 0.25
│   │   └── case1.txt
│   ├── 0.30
│   │   └── case1.txt
│   ├── 0.35
│   │   └── case1.txt
│   └── 0.45
│       └── case1.txt
├── case2
│   ├── 0.25
│   │   └── case2.txt
│   ├── 0.30
│   │   └── case2.txt
│   ├── 0.35
│   │   └── case2.txt
│   └── 0.45
│       └── case2.txt
└── foo
    ├── case1_0_25_case1.txt
    ├── case1_0_30_case1.txt
    ├── case1_0_35_case1.txt
    ├── case1_0_45_case1.txt
    ├── case2_0_25_case2.txt
    ├── case2_0_30_case2.txt
    ├── case2_0_35_case2.txt
    └── case2_0_45_case2.txt

11 directories, 16 files

相关内容