
我試圖讓 GNU 查找排除條目直至指定的檔案名稱。
拿這個樣本樹:
./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt
( 和其他目錄中也會有一堆其他文件world
,這就是為什麼我不簡單地搜尋hello.txt
)。
我想匹配除“test.txt”及其父目錄之外的所有內容。
輸出應該只是foo/bar/world/hello.txt
.
該命令會產生正確的結果,但它非常混亂,如果有多個同名目錄,則會產生錯誤的結果:
find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world
答案1
告訴find
您只對文件感興趣,而不是目錄。
find ./foo -type f ! -name test.txt
更新:
假設我們有這個稍微複雜一點的例子:
$ find ./foo
./foo
./foo/baz
./foo/baz/b.csv
./foo/baz/a.txt
./foo/bar
./foo/bar/c.txt
./foo/bar/world
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
如果您的目標是刪除內容,則需要指定-depth
檔案在其目錄之前顯示:
$ find ./foo -depth
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
如果您知道要保留的路徑,我們可以設計一個與其位元相符的正規表示式:
$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
然後我們可以否定正規表示式來取得您想要刪除的內容:
$ find ./foo -depth -regextype posix-extended ! -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
答案2
如果您知道樹的確切深度(即您想從第三個資料夾開始獲取檔案),您可以使用:
find . -mindepth $depth ! -name test.txt
根據您的目錄結構,我得到:
$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt
這正是您所期望的。
編輯:這應該會更好(但更難看!)。它會尋找所在test.txt
目錄並查找其中的所有檔案。優點是它完全獨立於父路徑,它會自動計算它們。
EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"
多行更好:
EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"