recursive - linux shell find directory
如何在find中排除目錄。 命令 (20)
我試圖為所有JavaScript文件運行find命令,但是如何排除特定目錄?
這是我們使用的查找代碼。
for file in $(find . -name '*.js'); do java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file; done
-path -prune方法也適用於路徑中的通配符。 下面是一個find語句,它將查找git服務器的目錄,該服務器為多個git存儲庫提供了git內部目錄:
find . -type d \
-not \( -path */objects -prune \) \
-not \( -path */branches -prune \) \
-not \( -path */refs -prune \) \
-not \( -path */logs -prune \) \
-not \( -path */.git -prune \) \
-not \( -path */info -prune \) \
-not \( -path */hooks -prune \)
-prune
絕對有效,並且是最好的答案,因為它可以防止下降到你想要排除的目錄中。 -not -path
仍然搜索排除的目錄,它只是不打印結果,如果排除的目錄被裝入網絡卷或者你沒有權限,這可能是一個問題。
棘手的部分是, find
是非常關注參數的順序,所以如果你沒有把它們恰到好處,你的命令可能無法正常工作。 參數的順序通常是這樣的:
find {path} {options} {action}
{path}
:首先放置所有與路徑有關的參數,如. -path './dir1' -prune -o
. -path './dir1' -prune -o
{options}
:在將-name, -iname, etc
作為這個組的最後一個選項時-name, -iname, etc
我獲得了最大的成功。 例如-type f -iname '*.js'
{action}
:你會想在使用-prune
時添加-print
這是一個工作示例:
# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js
# search for *.js, exclude dir1
find . -path './dir1' -prune -o -type f -iname '*.js' -print
# search for *.js, exclude dir1 and dir2
find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print
一種選擇是使用grep排除包含目錄名的所有結果。 例如:
find . -name '*.js' | grep -v excludeddir
例如,如果要排除misc
目錄,只需將-path ./misc -prune -o
添加到find命令中即可使用prune開關:
find . -path ./misc -prune -o -name '*.txt' -print
以下是多個目錄的示例:
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print
在這裡,我們排除dir1,dir2和dir3,因為在find
表達式中它是一個動作,作用於條件-path dir1 -o -path dir2 -o -path dir3
(如果dir1或dir2或dir3),與typed 。 進一步的行動是-o print
,只是打印。
如果-prune
不適合你,這將會:
find -name "*.js" -not -path "./directory/*"
對於FreeBSD用戶:
find . -name '*.js' -not -path '*exclude/this/dir*'
對於工作解決方案(在Ubuntu 12.04(Precise Pangolin)上測試)...
find ! -path "dir1" -iname "*.mp3"
將搜索除dir1子文件夾以外的當前文件夾和子文件夾中的MP3文件。
使用:
find ! -path "dir1" ! -path "dir2" -iname "*.mp3"
...排除dir1和dir2
對於那些不能使用-path或-not的舊版UNIX的用戶
測試SunOS 5.10 bash 3.2和SunOS 5.11 bash 4.4
find . -type f -name "*" -o -type d -name "*excluded_directory*" -prune -type f
您可以使用修剪選項來實現此目的。 如例如:
find ./ -path ./beta/* -prune -o -iname example.com -print
或者反向grep“grep -v”選項:
find -iname example.com | grep -v beta
您可以在Linux中查找詳細的說明和示例find命令排除搜索目錄 。
我嘗試了上面的命令,但沒有一個使用“-prune”的人為我工作。 最終我用下面的命令試了一下:
find . \( -name "*" \) -prune -a ! -name "directory"
我在這個頁面上發現了一些建議,很多其他頁面在我的Mac OS X系統上不起作用。 但是,我發現了一種對我有用的變體。
最主要的想法是搜索Macintosh HD,但避免遍歷所有外部卷,這些卷主要是Time Machine備份,映像備份,裝載共享和歸檔,但無需全部卸載它們,這通常是不切實際的。
這是我的工作腳本,我已經命名為“findit”。
#!/usr/bin/env bash
# inspired by http://.com/questions/4210042/exclude-directory-from-find-command Danile C. Sobral
# using special syntax to avoid traversing.
# However, logic is refactored because the Sobral version still traverses
# everything on my system
echo ============================
echo find - from cwd, omitting external volumes
date
echo Enter sudo password if requested
sudo find . -not \( \
-path ./Volumes/Archive -prune -o \
-path ./Volumes/Boot\ OS\ X -prune -o \
-path ./Volumes/C \
-path ./Volumes/Data -prune -o \
-path ./Volumes/jas -prune -o \
-path ./Volumes/Recovery\ HD -prune -o \
-path ./Volumes/Time\ Machine\ Backups -prune -o \
-path ./Volumes/SuperDuper\ Image -prune -o \
-path ./Volumes/userland -prune \
\) -name "$1" -print
date
echo ============================
iMac2:~ jas$
各種路徑都與外部存檔卷,Time Machine,虛擬機,其他掛載的服務器等有關。 一些卷名中有空格。
一個好的測試運行是“findit index.php”,因為該文件出現在我的系統的許多地方。 使用此腳本,搜索主硬盤需要大約10分鐘的時間。 沒有這些排除,它需要幾個小時。
我更喜歡-not
notation ...它更可讀:
find . -name '*.js' -and -not -path directory
我發現C源文件中的函數名稱排除* .o並排除* .swp和exclude(不是常規文件),並使用此命令排除dir輸出:
find . \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
有很多很好的答案,它只是花了我一些時間來了解命令的每個元素是什麼以及它背後的邏輯。
find . -path ./misc -prune -o -name '*.txt' -print
find將開始在當前目錄中查找文件和目錄,因此find .
。
-o
選項表示邏輯或,並分隔命令的兩個部分:
[ -path ./misc -prune ] OR [ -name '*.txt' -print ]
任何不是 ./misc目錄的目錄或文件都不會傳遞第一個測試-path ./misc
。 但是他們會根據第二種表達方式進行測試。 如果他們的名字對應於*.txt
模式,那麼他們會打印,因為有-print
選項。
當查找到達./misc目錄時,該目錄僅滿足第一個表達式。 所以-prune
選項將應用於它。 它告訴find命令不探索該目錄。 因此./misc中的任何文件或目錄都不會被查找探索,也不會針對錶達式的第二部分進行測試,也不會被打印。
比for
循環更好地使用exec
操作:
find . -path "./dirtoexclude" -prune \
-o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;
exec ... '{}' ... '{}' \;
將為每個匹配文件執行一次,用當前文件名替換大括號'{}'
。
請注意,大括號用單引號括起來,以防止它們被解釋為shell腳本標點符號* 。
筆記
*從find (GNU findutils) 4.4.2
手冊頁的EXAMPLES部分
這是唯一為我工作的人。
搜索除“目錄”之外的“NameOfFile”。 強調星星*。
find / -name NameOfFile ! -path '*/Directory/*'
這是我用來排除某些路徑的格式:
$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"
我用它來查找所有不在“。*”路徑中的文件:
$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
這適用於Mac上的我:
find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune
它將排除vendor
和app/cache
目錄搜索名稱後綴為php
。
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune