Find
如何使用 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 的語法中遺漏一些重要的東西。(我想使用 find 因為在某些日期之前和之後的文件會得到不同的處理。)
我的解決方案是呼叫 subshell,建構路徑,製作目錄,製作連結……大致(例如,未使用此處的範例進行測試):
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
行不通的;除非源是目錄,否則它不起作用)。您可以嘗試
-r
GNU 的選項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,請更改
gxargs
為xargs
和。gln``ln