Find

如何使用 find + xargs 在保持相對目錄樹的同時對選定文件進行符號連結(使用 gnu cp -s)

  • October 10, 2018

我正在嘗試將目錄結構中的選擇文件複製為重複目錄中的符號連結,例如

從這樣的目錄結構:

../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 的語法中遺漏一些重要的東西。(我想使用 find 因為在某些日期之前和之後的文件會得到不同的處理。)

我的解決方案是呼叫 subshel​​l,建構路徑,製作目錄,製作連結……大致(例如,未使用此處的範例進行測試):

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, $ 路徑2;在這個例子中混淆了 $1 與“1”和“2”的 b/c)。

如果您不使用-r參數遞歸地複制目錄,cp則不會為您創建任何中間目錄。(只是添加是-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和。gln``ln

引用自:https://unix.stackexchange.com/questions/473148