私の親ディレクトリには150のディレクトリがあります。それらのいくつかは.txt
文書を持ち、他のものはそうではありません。ファイルのないフォルダを印刷したいです.txt
。この目標をどのように達成できますか?
答え1
for dir in */; do
set -- "$dir"/*.txt
[ ! -e "$1" ] && printf '%s\n' "$dir"
done
これは現在のディレクトリのすべてのディレクトリを繰り返します。ディレクトリごとに、.txt
位置set
引数(、など)をパターンに一致するファイルのパス名$1
に設定し、何も一致しない場合はパターン自体に設定します。このファイル名拡張の最初の結果が既存のファイルのパス名でない場合は、ディレクトリ名が印刷されます。$2
$1
現在のディレクトリを含むすべてのディレクトリに対してこの操作を繰り返し実行するには、次の手順を実行します。
find . -type d -exec sh -c '
for dir do
set -- "$dir"/*.txt
[ ! -e "$1" ] && printf "%s\n" "$dir"
done' sh {} +
find
これはディレクトリパス名のジェネレータとして使用されます。まとめて見つかったディレクトリパス名に対して以前と同じループを実行して、含まれていない名前を印刷します.txt
。
上記の両方のコードは、次の項目の存在を検出します。どの名前はで終わります.txt
。興味がある場合一般ファイル(または一般ファイルへのシンボリックリンク)以下をループ本体として使用します。
while [ "$#" -gt 0 ] && [ ! -f "$1" ]; do
shift
done
[ ! -e "$1" ] && ...as above...
含む隠されたファイル名(withのbash -O dotglob -c
代わりに使用するなど)これにより、シェルループのファイル名グロービングがドットで始まる名前も考慮されます。最初のバリエーションでは、ループを実行するときにシェルオプションを設定する必要があります。sh -c
find
dotglob
shopt -s dotglob
bash
答え2
私は次の方法でこれを達成できました。
#!/bin/bash
search_dir=~/tmp
dirs=( $( find "$search_dir" -type f -name "*.txt" -exec dirname {} \; | sort -u ) )
exclude=()
for dir in "${dirs[@]}"; do
exclude+=( -not -path "$dir" )
done
find "$search_dir" "${exclude[@]}" -type d
変数をsearch_dir
使用する親ディレクトリに変更します。
次に、dirs
各ディレクトリに配列を設定します。する.txt ファイルが含まれています。
exclude
その後、各ディレクトリはに入力できる形式で配列に追加されますfind
。次に、除外配列にないすべてのディレクトリに対して親ディレクトリを再度検索します。