
例如,我有許多類似於下面輸出的文件,我試圖獲取所有唯一文件名的列表,但忽略“-”右側的字元。我嘗試過ls -la | grep ....- | sort --unique
一些變化,但這並沒有給出我需要的輸出
4855-00160880.psi
4855-00160980.ps
4855-00160980.psi
5355-00160880.ps
5355-00160880.psi
5355-00160980.ps
5355-00160980.psi
5855-00160880.ps
5855-00160880.psi
5855-00160980.ps
5855-00160980.psi
5855-00160A80.ps
5855-00160A80.psi
理想情況下,我希望輸出顯示類似的內容
4855
5355
5855
答案1
自從你真的不想解析ls
,這應該可以解決問題:
find . -type f -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
答案2
這個怎麼樣?
printf "%-4.4s\n" ????-* | uniq
shell 依字母順序擴展通配符並將結果作為參數傳遞給printf
.格式字串將每個參數截斷為四個字元並添加換行符。現在剩下的就是刪除相鄰的重複項。
如果您不知道連字號之前的位數,但您有一個想法,您可以循環一些候選人:
for expr in '??' '???' '????' '?????' # Quoted (!)
do
printf "%-${#expr}.${#expr}\n" $expr-* | # Unquoted!
uniq
done
這僅使用 Bash參數擴充 $[#var}
從而獲得 的字串長度$var
。
請注意引用通配符以避免它們在循環初始化中擴展的技巧,然後在循環內使用未加引號的變數(在大多數其他情況下這是禁忌)。
答案3
值得添加-type f
到 DopeGhoti 的答案中,以避免出現虛假.
結果。
find . -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
.
4855
5355
5855
find . -maxdepth 1 -type f -exec basename "{}" \; | cut -d'-' -f1 | sort -u
4855
5355
5855
$
如果希望與您最初的嘗試保持相似,您可以使用這個(不好,因為它解析ls
!)
ls -1 | grep ^....- | cut -c1-4 | sort --unique
基於 awk 的解決方案,仍在解析 ls
ls -1 | awk -F- '{print $1}' | sort --unique
在每種情況下都不需要進行排序,因為ls
輸出已經排序,所以可以只使用uniq
.
ls -1 | awk -F- '{print $1}' | uniq
基於sed的解決方案
ls -1 | sed 's/-.*//' | uniq
find / sed 避免解析 ls 的解
find . -type f -printf "%f\n" | sed 's/-.*//g' | sort --unique
如果「-」之前總是 4 位數字,那麼這非常優雅
find . -type f -printf "%.4f\n" | sort -u
答案4
和zsh
:
myfiles=(*-*(.))
print -rl -- ${(u)myfiles[@]%%-*}
這會將至少包含一個破折號的所有常規檔案名稱保存在陣列中。然後,它對數組的每個元素使用參數擴充來刪除第一個破折號和後面的所有內容。任何重複的元素都會透過標誌刪除(u)
。
若要也選擇隱藏文件,請使用myfiles=(*-*(.D))