如何使用 find + xargs 建立指向选定文件的符号链接,同时保留相对目录树(使用 gnu cp -s)

如何使用 find + xargs 建立指向选定文件的符号链接,同时保留相对目录树(使用 gnu cp -s)

我正在尝试将目录结构中的选定文件复制为重复目录中的符号链接,例如

从这样的目录结构:

../1/a/data1.txt
../1/a/file1.txt
../1/a/b/file2.txt

做这个:

../2/a/file1.txt -> ../../1/a/file1.txt
../2/a/b/file2.txt -> ../../2/a/b/file1.txt

例如,保留目录树并跳过匹配各种模式的文件。

当我从目标目录 (../2/a) 使用 GNU cp 替换相对路径时,一切都按我想要的方式工作,除了它复制 data1.txt:

gcp -rs $(cd ../..; pwd)/1/a/* $PWD/

但是当我在 find + xargs 中使用它来排除某些文件时,

find  -X -f $(cd ../..; pwd)/1/a \! -name '*data*' -type f | xargs -t -n1 -I % gcp -s -t $PWD/ %

我明白了:

../2/a/file1.txt -> ../1/a/file1.txt
../2/a/file2.txt -> ../1/a/b/file2.txt

例如,目录结构没有被复制。我可以想象繁琐的解决方法,但我一定错过了 xargs 语法中的一些重要内容。 (我想使用查找,因为某些日期之前和之后的文件会得到不同的处理。)

我的解决方案是粗略地调用子shell、构造路径、创建目录、创建链接(例如,未使用此处的示例进行测试):

find $(cd ../..; pwd) -type f \! -name '*data*' -print0 | xargs -0 bash -c 
     'while [ -n "$1" ]; do
           TMP="${1%$(basename $1)}"; 
           mkdir -p "${TMP/1/2}";  
           gcp -s "$1" "${1/1/2}"; 
           shift;
      done;' "bash"

因为这是在脚本内调用的,所以在命令之前我导出了相关的路径名(这里的“1”和“2”实际上是 $PATH1、$PATH2;在这个示例中,$1 的 b/c 与“1”和“2”令人困惑”)。

答案1

如果您不使用参数递归复制目录-rcp则不会为您创建任何中间目录。 (仅仅添加是-r行不通的;除非源是一个目录,否则它没有效果)。

您可以尝试-rGNU 的选项ln(“创建相对链接”),并使用mkdir -p {dirname}.例子:

# usage mklinks from to [opts/predicates for find ..]
mklinks(){
    from=$1; shift
    to=$1; shift
    find "$from" -type f "$@" -print0 | from=$from to=$to gxargs -0 sh -c '
        for a; do
            t="$to/${a#$from}"; b=${t##*/}
            mkdir -vp "${t%$b}" && gln -vrs "$a" "$t"
        done
    ' sh
}

mklinks ../../1/a . \! -name '*data*'

当然,如果您使用的是 linux,请更改gxargsxargs和。glnln

相关内容