查找包含數字的文件名
我想查找包含數字的文件名並將它們列出在一系列數字中。例如,在我的目錄中,我有:**
Ion_001_rawlib.bam Ion_002_rawlib.bam Ion_003_rawlib.bam Ion_004_rawlib.bam Ion_005_rawlib.bam ... Ion_020_rawlib.bam
**
我只想列出從 003 到 005 的 Ion 文件名。我試圖做這樣的事情:
find -name '*Ion_*[3-5]*rawlib.bam'
但它不會產生預期的效果。你知道它是否可以執行嗎?謝謝。
使用
zsh
外殼,您可以執行以下操作:print -rC1 Ion_<3-5>_rawlib.bam
Where
<x-y>
是一個 glob 運算符,它匹配給定範圍內的正整數的文本十進製表示(從x
到y
,包括在內)。遞歸:
print -rC1 -- **/Ion_<3-5>_rawlib.bam
(
(D)
如果您還想在隱藏文件夾中查找這些文件,或者(N)
如果您不想在沒有匹配文件時將其視為錯誤,請添加)。使用
find
支持-regex
謂詞的實現,您可以執行以下操作:LC_ALL=C find . -regex '.*/Ion_0*[345]_rawlib\.bam'
*
(匹配 0 或更多 ( ) 字節 (.
withLC_ALL=C
) 後跟/Ion_
0 或更多 (*
)的文件路徑,0
後跟3
,4
或5
字元之一rawlib.bam
)。在這裡,3..5 範圍相對容易,但對於 78..123 之類的範圍會變得更加痛苦(並且您會遇到兼容性問題,因為那裡支持使用不同格式的正則表達式的少數
find
實現-regex
)。標準
find
僅支持-name
和-path
用於匹配文件名,它使用基本的 shell 萬用字元而不是正則表達式來完成,但萬用字元沒有*
regexp 運算符的等效項(前面的原子的 0 個或多個),它的*
運算符等效於 regexp.*
(0 個或多個字元),因此Ion_*[3-5]_rawlib.bam
將匹配 onIon_9994_rawlib.bam
例如*
匹配 on999
。然而,在這個簡單的情況下,您可以使用幾種模式和否定來完成,例如:
LC_ALL=C find . -name 'Ion_*[345]_rawlib.bam' \ ! -name 'Ion_*[!0]*?_rawlib.bam'
非遞歸:
LC_ALL=C find . ! -name . -prune \ -name 'Ion_*[345]_rawlib.bam' \ ! -name 'Ion_*[!0]*?_rawlib.bam'
x
要在名稱中的任何位置查找包含整數的十進製表示的文件y
,您需要一個與該範圍匹配的模式(如zsh
’s<x-y>
),但還要確保該模式不被其他數字包圍。例如foo305.txt
確實包含3
,05
和5
, 所有這些都匹配<3-5>
。在
zsh
中,那將是:print -rC1 -- (|*[^0-9])<3-5>(|[^0-9]*)
即
<3-5>
(匹配 3、03、003…)之後是空字元或以非數字結尾的字元串,然後是空字元或以非數字開頭的字元串。使用 BSD
find
:LC_ALL=C find -E . -regex '.*/([^/]*[^0-9])?0*[3-5]([^0-9][^/]*)?'
與 GNU
find
相同,但替換-E .
為. -regextype posix-extended
.使用busybox
find
(儘管取決於它的編譯方式):busybox find . -regex '.*/\([^/]*[^0-9]\)\?0*[3-5]\([^0-9][^/]*\)\?'
另一種方法是使用
find
報告文件列表,但使用更高級的語言perl
來過濾該列表:find . -print0 | perl -l -0ne ' if (m{[^/]*\z}) { for $n ($& =~ /\d+/g) { if ($n >= 3 && $n <= 5) { print; next LINE; } } }'
在這裡,使用
perl
從每個文件的基本名稱中提取所有十進制數字序列,如果這些數字序列中至少有一個表示 3..5 範圍內的數字,則輸出文件。