Bash

Bash:移動特定模式的文件

  • September 24, 2015

我編寫了一個腳本,它遍歷一組 zip 文件,提取它們並僅將與特定文件名模式匹配的文件移動到另一個文件夾。

劇本:

#!/bin/bash

ARCHIVE_FILEMASK="????-??-??_E_MDT_0_0.7z"
FILEMASK="?????????_?????_A_?_????????????????-?????????"
extractDir=/path/to/dir
dest=/path/to/dest

for f in ${ARCHIVE_FILEMASK}
do
   7z e -aoa -o"${extractDir}" "$f"
   if [ $? != 0 ]
   then
       mv "${extractDir}/${FILEMASK}".xml "$dest"
   fi
done

執行腳本時發生錯誤:

mv: cannot stat `/path/to/dir/?????????_?????_A_?_????????????????-?????????.xml': No such file or directory

我已經嘗試打開 nullglob 和 extglob,但沒有幫助。如果我直接從 shell 執行命令,它執行得很好。其他有類似問題的文章的答案也沒有幫助。

編輯: 在 Paweł Rumian 提到目錄名稱中的空格可能存在問題後,我嘗試了 AVJ 的提示並在命令set +x之前添加。mv

結果是:

+ mv '/path/to/dir/?????????_?????_A_?_??????????????????-????? ????.xml' /path/to/dest

所以很明顯我現在必須擺脫單引號。知道怎麼做嗎?

在變數擴展周圍加上雙引號的通常建議是,因為$foo外部引號的意思是“取 的值foo,將其拆分為空格¹,如果每個結果單詞與至少一個文件匹配,則將其擴展為萬用字元模式”,而不是“取值的foo”。特別是當變數foo包含文件名時,"$foo"是​​你需要的。但這裡的變數ARCHIVE_FILEMASKFILEMASK包含萬用字元模式。因此,您實際上確實希望在使用它們時擴展它們,因此您應該不加引號地使用它們。因此,它們將被解釋為以空格分隔的模式列表;這在這裡沒有什麼區別,因為這些變數的值中沒有空格。

變數fextractDir包含文件名,因此它們必須保持雙引號。

for f in ${ARCHIVE_FILEMASK}
do
   if 7z e -aoa -o"${extractDir}" "$f"; then
       mv "${extractDir}/"${FILEMASK}.xml "$dest"
   fi
done

由於您使用的是 bash,因此如果萬用字元模式與任何文件都不匹配,則可以呼叫shopt -s nullglob以將其擴展為空列表。如果您不向其傳遞任何源文件,"${extractDir}/"${FILEMASK}.xml該命令將抱怨它缺少文件;mv您可以通過僅在至少有一個匹配項時呼叫它來解決該問題。

shopt -s nullglob
for f in ${ARCHIVE_FILEMASK}
do
   if 7z e -aoa -o"${extractDir}" "$f"; then
       matches=("${extractDir}/"${FILEMASK}.xml)
       if ((${#matches[@]})); then
           mv "${matches[@]}" "$dest"
       fi
   fi
done

¹或更一般地,如 所示IFS

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