如何从递归文件复制中排除特定扩展名?

spr*_* cc 6 command-line cp

我想将除名为 *.data 的数据文件之外的所有文件和子目录复制到目标目录。

 [ichen@ui01 sub_test]$ ls
a.cxx  a.data  subdir
[ichen@ui01 sub_test]$ ls subdir/
sub_a.cxx  sub_a.data
Run Code Online (Sandbox Code Playgroud)

可以看到,outside dir和subdir分别有2个数据文件。我使用了这个命令:

[ichen@ui01 sub_test]$ cp -r !(*.data) ../destination_dir/
Run Code Online (Sandbox Code Playgroud)

旨在将除 *.data 之外的所有文件复制到目的地,但它在子目录中不起作用:

  [ichen@ui01 destination_dir]$ ls
a.cxx  subdir
[ichen@ui01 destination_dir]$ ls subdir/
sub_a.cxx  sub_a.data
Run Code Online (Sandbox Code Playgroud)

您可以在上面看到此命令仅适用于第一个目录,如何使其适用于所有子目录?

Mtt*_*ocy 1

您没有在问题中指定是否需要保留副本中的目录结构,或者是否只需要文件的副本。要简单地复制所有未命名为 *.data 的文件,您可以使用以下命令:

find . -type f ! -name '*.data' | xargs cp -t ../destination_dir/
Run Code Online (Sandbox Code Playgroud)

另一方面,如果你想保留目录结构,你可以使用这样的东西:

for file in `find . ! -name '*.txt' | sed 's/^.\///'`; do if [ -d "./$file" ]; then mkdir -p "../destination_dir/$file"; else cp "./$file" "../destination_dir/$file"; fi; done
Run Code Online (Sandbox Code Playgroud)

不确定是否有更简单的方法来执行此操作,但此命令执行以下操作:

查找当前目录或其子文件夹中与 *.data 不匹配的所有文件和文件夹,然后分别查找:

测试该文件是否是一个目录,如果它在目标目录下创建一个匹配的目录,或者如果它是一个文件,则将其复制到目标。

编辑:添加 shell 脚本版本:

#!/bin/bash

# Disable shell glob expansion within the script
# Required to stop bash from expndinging the glob in $1
set -f

for file in `find . ! -name $1 | sed 's/^.\///'`
  do if [ -d "./$file" ]; then
    mkdir -p "$2/$file"
  else
    cp "./$file" "$2/$file"
fi
done
Run Code Online (Sandbox Code Playgroud)