ディレクトリのサブディレクトリを一覧表示するには?

ディレクトリのサブディレクトリを一覧表示するには?

特定のパスのサブディレクトリを一覧表示する必要があります。区切りは改行文字ではなく空白でなければなりません。

また、サブディレクトリへの絶対パスは望ましくなく、その名前のみが必要です。

# correct
dir1 dir2 dir3

# incorrect: separation with new lines
dir1
dir2
dir3

# incorrect: absolute paths
/home/x/y/dir1 /home/x/y/dir2 /home/x/y/dir3

他の記事もたくさん見ましたが、この投稿しかし、彼らは私の要求を満たしていません。

私はこれを試しましたが、ls -d ~/y新しい行で区切られた絶対パスをリストします。私はsedを使用してパスから無関係な部分を削除し、すべての新しい行を削除できると思いました。しかし、動作させることはできません。より良い解決策があるはずです。

ベストアンサー1

GNUツールを使用していると仮定すると、GNUを使用して特定のディレクトリbasenameにあるすべてのサブディレクトリの名前を取得できます。その後、pasteスペースで区切られたリストにフォーマットすることができます。

basename -a /some/path/*/ | paste -d ' ' -s -

上記のコマンドは、GNUがコマンドラインからオペランドとして指定された複数のパス名のうち、ファイル名の部分を返すことができるというbasename事実を利用します。-a

で終わるファイル一致パターンを使用して/GNUパス名を生成しますbasename。ディレクトリのみがこれらのパターンと一致できます。

最後に、pasteGNUで生成された改行で区切られたリストからスペースで区切られたリストを作成しますbasename

元のディレクトリ名に空白文字が含まれている場合、結果のファイル名のリストを解析することは困難です。

ディレクトリにシンボリックリンクが含まれている場合、このメソッドはそのシンボリックリンクに従おうとします。


外部ツールの使用を制限するために、シェルの配列を使用してディレクトリbashパスを保存および操作できます。

shopt -s nullglob

topdir=/some/path

dirpaths=( "$topdir"/*/ )
dirpaths=( "${dirpaths[@]#$topdir/}" )
dirpaths=( "${dirpaths[@]%/}" )

printf '%s\n' "${dirpaths[*]}"

上記のシェルコードは、この回答の最初の部分で使用したのと同じワイルドカードパターンを拡張しますが、結果のディレクトリパスを配列に保存しますdirpaths。次に、$topdir/配列の各要素とそれに続く要素から既知の接頭辞を削除し、配列を/スペースで区切られた名前の単一の文字列として印刷します。最後の行の名前の間に使用される区切り文字は、デフォルトでは空白の$IFS最初の文字です。


を使用すると、find最上位ディレクトリ自体が返されないようにしながら、関心のある特定の最上位ディレクトリ内のサブディレクトリを見つけることができます。また、サブディレクトリの入力も停止しますfind

topdir=/some/path
find "${topdir%/}/." ! -name . -prune -type d -exec basename {} \; | paste -d ' ' -s -

上記のコマンドは開始点の検索を避けるためにネガティブテストを使用し、-name検索ツリーをクリーンアップしてサブディレクトリに繰り返さないようにします-prune。見つかった各ディレクトリをfind呼び出して、basenameディレクトリのファイル名を別々の行に出力します。最後のステップにfind結果をパイプして、paste1行にスペースで区切られたリストとして出力形式を指定します。

GNUでは、find次のように書くことができます。

find /some/path -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | paste -d ' ' -s -

このように使用すると、find隠された名前のディレクトリが一覧表示され、シンボリックリンクされたディレクトリは表示されません。


シェルでは、zsh高度なシェルグローブモードを使用してディレクトリのファイル名のみを選択し、一度にすべて印刷できます。

print -r -- /some/path/*(/:t)

/:tこのコマンドは2つの部分で構成され、以前のglobingモードに影響を与えるglob修飾子を使用します/some/path/*。生成された各パス名のファイル名部分である「尾」を抽出する間、パターンはディレクトリ/(シンボリックリンクされたディレクトリではなく、その目的のために-/)のみに一致するようにします。:t

このコマンドは、拡張データ内のエスケープprint -rシーケンス(たとえば、または)を回避しながら、引数を印刷するためにスペースを区切り文字として使用します。区切られたオプション(シェルの操作にも適用されます)にオペランドを使用すると、glob拡張で作成されたディレクトリ名がで始まってもオプションとして処理されません。\n\t---ksh-

bashシェルでこれを使用してリストを作成できます。

zsh -c 'print -r -- /some/path/*(/:t)'

おすすめ記事