Bash

使用 rsync 刪除選定的模式,匹配所有文件

  • October 2, 2018

我的意思是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"

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