[英]How do I recursively list all directories at a location, breadth-first?
在這里,廣度優先列表很重要。 另外,限制搜索的深度會很好。
$ find . -type d
/foo
/foo/subfoo
/foo/subfoo/subsub
/foo/subfoo/subsub/subsubsub
/bar
/bar/subbar
$ find . -type d -depth
/foo/subfoo/subsub/subsubsub
/foo/subfoo/subsub
/foo/subfoo
/foo
/bar/subbar
/bar
$ < what goes here? >
/foo
/bar
/foo/subfoo
/bar/subbar
/foo/subfoo/subsub
/foo/subfoo/subsub/subsubsub
如果可能的話,我想使用 bash 單行代碼來做到這一點。 如果有一個javascript-shell,我會想象像
bash("find . -type d").sort( function (x) x.findall(/\//g).length; )
find
命令支持-printf
選項,它可以識別很多占位符。
一個這樣的占位符是%d
,它呈現給定路徑的深度,相對於find
開始的位置。
因此,您可以使用以下簡單的一行代碼:
find -type d -printf '%d\t%P\n' | sort -r -nk1 | cut -f2-
它非常簡單,不依賴於像perl
這樣的重型工具。
怎么運行的:
如果你想使用標准工具來完成它,下面的管道應該可以工作:
find . -type d | perl -lne 'print tr:/::, " $_"' | sort -n | cut -d' ' -f2
那是,
要限制找到的深度,請將 -maxdepth 參數添加到查找命令。
如果您希望目錄以與 find 輸出它們相同的順序列出,請使用“sort -n -s”而不是“sort -n”; “-s”標志穩定排序(即,保留比較相等的項目之間的輸入順序)。
您可以使用 find 命令,find /path/to/dir -type d 下面是當前目錄中目錄的示例列表:
find . -type d
我的感覺是,這是比前面提到的更好的解決方案。 它涉及 grep 和循環,但我發現它工作得很好,特別是對於你想要緩沖行而不是緩沖完整查找的情況。
它需要更多的資源,因為:
這很好,因為:
#!/bin/bash depth=0 while find -mindepth $depth -maxdepth $depth | grep '.' do depth=$((depth + 1)) done
你也可以很容易地將它放在一條線上(?):
depth=0; while find -mindepth $depth -maxdepth $depth | grep --color=never '.'; do depth=$((depth + 1)); done
但我更喜歡小腳本而不是打字......
我認為您不能使用內置實用程序來完成此操作,因為在遍歷目錄層次結構時,您幾乎總是希望進行深度優先搜索,無論是自上而下還是自下而上。 這是一個 Python 腳本,可以為您提供廣度優先搜索:
import os, sys
rootdir = sys.argv[1]
queue = [rootdir]
while queue:
file = queue.pop(0)
print(file)
if os.path.isdir(file):
queue.extend(os.path.join(file,x) for x in os.listdir(file))
編輯:
os.path
-module 而不是os.stat
和stat
-module。list.pop
和list.extend
代替del
和+=
運算符。 我試圖找到一種使用find
來執行此操作的方法,但它似乎沒有-breadth
選項之類的東西。 如果沒有為它編寫補丁,請嘗試以下 shell 咒語(用於 bash):
LIST="$(find . -mindepth 1 -maxdepth 1 -type d)";
while test -n "$LIST"; do
for F in $LIST; do
echo $F;
test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)";
done;
LIST=$NLIST;
NLIST="";
done
我有點偶然發現了這個,所以我不知道它是否一般有效(我只在你詢問的特定目錄結構上測試它)
如果你想限制深度,在外循環中放置一個計數器變量,就像這樣(我也在為這個添加注釋):
# initialize the list of subdirectories being processed
LIST="$(find . -mindepth 1 -maxdepth 1 -type d)";
# initialize the depth counter to 0
let i=0;
# as long as there are more subdirectories to process and we haven't hit the max depth
while test "$i" -lt 2 -a -n "$LIST"; do
# increment the depth counter
let i++;
# for each subdirectory in the current list
for F in $LIST; do
# print it
echo $F;
# double-check that it is indeed a directory, and if so
# append its contents to the list for the next level
test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)";
done;
# set the current list equal to the next level's list
LIST=$NLIST;
# clear the next level's list
NLIST="";
done
(將-lt 2
中的 2 替換為深度)
基本上,這實現了標准的廣度優先搜索算法,使用$LIST
和$NLIST
作為目錄名稱隊列。 這是后一種方法,作為易於復制和粘貼的單行方法:
LIST="$(find . -mindepth 1 -maxdepth 1 -type d)"; let i=0; while test "$i" -lt 2 -a -n "$LIST"; do let i++; for F in $LIST; do echo $F; test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)"; done; LIST=$NLIST; NLIST=""; done
沒有應有的順序:find -maxdepth -type d
要獲得應有的順序,您必須使用這個小的 shellscript 自己進行遞歸:
#!/bin/bash
r ()
{
let level=$3+1
if [ $level -gt $4 ]; then return 0; fi
cd "$1"
for d in *; do
if [ -d "$d" ]; then
echo $2/$d
fi;
done
for d in *; do
if [ -d "$d" ]; then
(r "$d" "$2/$d" $level $4)
fi;
done
}
r "$1" "$1" 0 "$2"
然后你可以用參數基目錄和深度調用這個腳本。
這是一種可能的方法,使用 find。 我還沒有徹底測試它,所以用戶要小心......
depth=0
output=$(find . -mindepth $depth -maxdepth $depth -type d | sort);
until [[ ${#output} -eq 0 ]]; do
echo "$output"
let depth=$depth+1
output=$(find . -mindepth $depth -maxdepth $depth -type d | sort)
done
像這樣:
find . -type d |
perl -lne'push @_, $_;
print join $/,
sort {
length $a <=> length $b ||
$a cmp $b
} @_ if eof'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.