strings.txt
我有一個包含字串列表的文件:
GCA_001677475.1
GCA_003410275.1
GCA_002310615.1
GCA_000007405.1
GCA_000219515.3
我的目錄中有許多文件,其名稱如下:
GCA_000005845.2_ASM584v2_protein.faa
GCA_000006925.2_ASM692v2_protein.faa
GCA_000007405.1_ASM740v1_protein.faa
GCA_000007445.1_ASM744v1_protein.faa
GCA_000008865.2_ASM886v2_protein.faa
GCA_000009565.2_ASM956v1_protein.faa
我只需要移動那些名稱以strings.txt
.到目前為止,我已經嘗試使用xargs
with mv
:
cat strings.txt | xargs -I % mv %*faa ./Data
但mv
不%*faa
視為正規表示式並嘗試尋找具有該確切名稱的檔案(當然它找不到任何檔案)。我也嘗試過使用,ls
但它的工作方式是相同的:
cat strings.txt | xargs -I {} ls {}*faa
那我該怎麼做呢?
答案1
xargs bash -O nullglob -c '
for prefix do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done' sh <strings.txt
這用於xargs
將字串批量提供strings.txt
給內聯bash
腳本。
對於每個字串,內聯bash
腳本測試當前目錄中是否有任何與該字串匹配的檔案名稱(添加*.faa
到末尾以建立模式),如果有,則將它們移動到該Data
目錄,假設該目錄已經存在。
為內聯腳本設定shellnullglob
選項,以確保建構的模式是否不是匹配任何內容,模式將被刪除(而不是保留未擴展)。
我正在明確測試模式是否匹配,因為您的範例中的某些字串與您顯示的任何檔案名稱都不匹配。這是透過將位置參數清單設為 glob 擴充的結果,然後測試清單的長度 ( $#
) 是否大於零來完成的。
顯然你也可以這樣做,而不是像xargs
這樣:
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done <strings.txt
這仍然會失敗如果您的前綴字串之一碰巧匹配數千個檔案名稱(mv
命令列會變得太長)。如果是這種情況,您可能會使用
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
if [ "$#" -gt 0 ]; then
printf '%s\n' "$@" | xargs sh -c 'mv -- "$@" ./Data' sh
fi
done <strings.txt
這是假設前綴字串和檔案名稱都不包含嵌入的換行符。
答案2
這是一個可能的解決方案:
cat strings.txt | xargs -I '%' find . -type f -name "%*" -exec mv -t your_path {} +
感動GCA_000007405.1_ASM740v1_protein.faa
那是唯一的匹配。
答案3
不需要xargs
或任何複雜的事情。如果所有檔案都位於同一目錄中,則執行以下操作就足夠了:
$ while read string; do
mv "$string"_* ./Data;
done < strings.txt
或者,如果您的名字可以以 a 開頭-
,或者其中可能有其他奇怪的字符,請使用:
$ while read -r string; do
mv -- "$string"_* ./Data;
done < strings.txt
答案4
快速而骯髒的駭客:cat strings.txt| xargs -i sh -c 'mv {}* your/path/'>&/dev/null
更少更正確的駭客:export dir=$(ls -1); cat strings.txt| xargs -i sh -c 'grep "^{}" <<<$dir && mv {}* your/path'; dir=""