Bash
使用 rsync 刪除選定的模式,匹配所有文件
我的意思是
rsync
用來刪除某些文件(用於有效刪除包含數千個文件的大目錄),在這種情況下,作為命令行中的模式提供給 shell 腳本。到目前為止,這就是我的 shell 腳本中的內容
rsync_del.sh
#!/bin/bash TARGET_DIR=${1} shift PATTERNS="${@}" for patt in ${PATTERNS} ; do # Both do the same #INCLUDE_PATTERNS="${INCLUDE_PATTERNS}"' --include='\'"${patt}"\' INCLUDE_PATTERNS="${INCLUDE_PATTERNS} --include=\"${pattern}\"" done EMPTYDIR=$(mktemp -d) echo "Created empty dir ${EMPTYDIR}" comm="rsync -a --progress --delete ${INCLUDE_PATTERNS} ${EMPTYDIR}/ ${TARGET_DIR}" echo ${comm} eval ${comm}
我想使用的範例模式是
*[1-9].txt
,*000??9.txt
。問題是,在執行時rsync_del.sh trg_dir '*[1-9].txt'
生成的命令行是
rsync -a --progress --delete --include='*[1-9].txt' /tmp/tmp.51R9hPgkfG/ trg_dir/
(這對我來說似乎沒問題),但它是匹配的,例如,像這樣的文件
input.dat
(我不想要那個)。實現/使用它的正確方法是什麼? 我懷疑這是正確轉義模式的問題,但我無法完成這項工作。
注意:我需要在執行
echo
之前定義要在變數中執行的命令。
我忘記了我應該通過排除任何未明確包含的內容來關閉模式列表。我用了
comm="rsync -a --progress --delete ${INCLUDE_PATTERNS} --exclude=\"*\" ${EMPTYDIR}/ ${TARGET_DIR}"
不要太仔細地看這裡的實際使用,
rsync
而是專注於rsync
命令行的創建。#!/bin/bash target=$1 shift empty=$( mktemp -d ) trap 'rmdir "$empty"' EXIT for pattern do incl+=( --include="$pattern" ) done rsync --archive --progress --delete "${incl[@]}" --exclude='*' "$empty"/ "$target"
通過使用數組(
incl
上面的數組),您可以單獨儲存參數,rsync
而不是像字元串一樣。的擴展"${incl[@]}"
將是數組中單獨引用的元素。引用參數變得微不足道,無需呼叫eval
. 另請注意,所有參數擴展都需要正確雙引號。您的程式碼的問題是您使用了大多數未引用的參數擴展。這使得 shell 對變數執行分詞和文件名生成(萬用字元)。這反過來意味著您不能使用包含空格的模式或可能擴展到現有文件名稱的 shell 通配模式。
因為
/bin/sh
語法變得更加簡潔:#!/bin/sh target=$1 shift empty=$( mktemp -d ) trap 'rmdir "$empty"' EXIT for pattern do set -- "$@" --include="$pattern" shift done rsync --archive --progress --delete "$@" --exclude='*' "$empty"/ "$target"