我在特定資料夾中有大量文件。我想將這些檔案移到子資料夾,前提是它們在第4 列的任何行中至少有1 個高於0.5 的值。 2 行具有上述值第 4 欄為 0.5。
這是文件的一般格式(帶標題):
col1 col2 col3 col4 col5 col6
ABC DEF 5.10 0.94 GHI JKL
MNO PQR 8.31 0.37 STU VWX
ABC DEF 6.49 0.84 GHI JKL
MNO PQR 3.32 0.21 STU VWX
第 4 列中的一些數字採用科學計數法:8.934553871039306e-05
下面的程式碼是我到目前為止嘗試移動第 4 列中至少有 1 個值高於 0.5 的檔案的程式碼。
#!/bin/bash
find . -type f -exec awk '$4 >= 0.5' {} \; -exec mv -n {} ./NewFolder/ \;
答案1
若要使指令正常運作,如果找到符合項,則必須awk
使用代碼 0 退出;如果未找到符合項,則必須使用非零退出代碼退出。
除此之外,您應該跳過第一行,因為非數字值將作為字串進行比較,這可能會導致意外的匹配。
find . -type f -exec awk 'FNR==1 {next} $4 >= 0.5 {found=1; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;
注意:如果awk
使用多個檔案呼叫腳本,則退出程式碼意味著在任何檔案中找到了匹配項。該find
命令將確保一次僅將一個文件傳遞給awk
,因此這裡不是問題。
第二次編輯:
若要選擇至少有 2 個符合行的文件,您可以對匹配項進行計數。
find . -type f -exec awk 'FNR==1 {next} $4 >= 0.5 {found++; if(found >= 2) exit} END {exit found >= 2}' {} \; -exec mv -n {} ./NewFolder/ \;
編輯:
要偵錯腳本移動第 4 列中沒有符合值的檔案的問題,您可以在腳本中新增程式碼awk
以列印有關匹配行的資訊。以下程式碼將列印檔案名稱、行號以及找到符合項目時的符合行。
find . -type f -exec awk 'FNR==1 {next} $4 >= 0.5 {found=1; printf "%s:%d:%s\n", FILENAME, FNR, $0; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;
你會得到類似的東西
threshold.txt:2:ABC DEF 5.10 0.94 GHI JKL
我建議先這樣做以找出問題的原因。
如果第 4 列中有一些行包含非數字文本,則這些值將作為文本進行比較。這將導致"abc"
例如大於"0.5"
。
另一個可能的原因可能是某行在第 1 列或第 2 列中包含空格,這將導致將文字錯誤分配到各列。
如果第 4 列中有非數字值並且您想要忽略這些行,您可以透過將值加到0
中來強制進行數字解釋0 + $4
。
find . -type f -exec awk 'FNR==1 {next} 0 + $4 >= 0.5 {found=1; printf "%s:%d:%s\n", FILENAME, FNR, $0; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;
如果問題的原因是您的欄位由製表符分隔且值可以包含空格,您可以指定欄位分隔符號 ( -F "\t"
)。以下腳本將此與其他修改結合。
find . -type f -exec awk -F "\t" 'FNR==1 {next} 0 + $4 >= 0.5 {found=1; printf "%s:%d:%s\n", FILENAME, FNR, $0; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;
答案2
您awk
實際上不起作用,它會找到所有文件,因為字串col4
滿足>=0.5
:
$ echo col4 | awk '$1>=0.5'
col4
所以你需要跳過標題。您還需要告訴 awk 如果文件符合您的條件則成功退出,如果不符合則失敗。像這樣的東西:
find . -type f \
-exec awk -va=1 '{ if($4 >= 0.5 && NR>1){a=0}} END{exit a}' {} \; \
-exec mv -n {} ./NewFolder/ \;
答案3
使用 for 循環,您可以嘗試以下操作:
for i in *; do # *.extension
[[ -f "$i" && $(awk 'NR>1 && $4 >= 0.5' "$i") ]] && mv "$i" NewFolder/
done
對於兩個值:
for i in *; do # *.extension
[[ -f "$i" ]] && [[ $(awk 'NR>1 && $4 >= 0.5' "$i" | wc -l) -ge 2 ]]
mv "$i" NewFolder
done