ディレクトリの名前が重要でない次のディレクトリ構造があるとしましょう。
currentDir/
Dir1
Dir1
Dir1 *
Dir2 *
Dir3 *
Dir2
Dir1 *
Dir2
Dir1*
Dir3*
ツリーブランチの最後のディレクトリのみに「Texture」という名前のディレクトリを作成できる方法はありますか(例では*
でマークされています)。これらのディレクトリのみがTexture
ディレクトリを取得し、他のディレクトリは取得しないようにします。
すべてのディレクトリにはファイルがある場合とない場合がありますが、エンドディレクトリには他のディレクトリはありません。
最初に再帰的グロビングをオンにします
shopt -s globstar
これで、**
を使用してすべてのディレクトリを検索できます。設定を解除するには、shopt -u globstar
を使用できます(デフォルトではオフになっているため、新しいシェルを開くとオフになります)。
以下のすべてで、テスト後にecho
を削除して、実際にディレクトリを作成します。
ツリーの終わりのディレクトリが空の場合、空かどうかをテストし、検出された場合にのみディレクトリを作成できます...
for d in **/; do [[ -z "$(ls -Aq "$d")" ]] && echo mkdir "$d"Texture; done
つまり、ls -A (hidden files except current and parent dir) -q (printing ? for non-printing characters)
の出力が空の場合、ディレクトリを作成します。
しかし、ディレクトリにはファイルが含まれているため、ディレクトリがないことをテストする方がよい
for d in **/; do [[ -z "$(find "$d" -maxdepth 1 -mindepth 1 -type d)" ]] && echo mkdir "$d"Texture; done
mindepth -1
は、見つかった現在のディレクトリを停止します... find
は隠しファイルを見るため、それらが含まれていることがわかります。すべての文字がテストに合格する必要があるため(出力が空であることを確認するだけです)、これはかなり安全です。
もっと簡潔な方法 (Sorry Greg) (しかし、実際にはこれらのメソッドはすべて同様にiffyを行います-実際にはこれらのファイルで何もしようとしていないので、テキストとしてファイル名を使用することで大体逃げることができますここ自体):
for d in **/; do (ls -Alq "$d" | grep -q '^d') || echo mkdir "$d"Textures; done
ここで、長い出力用に-l
フラグを追加します。これは、フォーム内のすべてのファイルを印刷します
drwxrwxr-x 5 zanna zanna 4096 Sep 27 22:00 Dir1
次に、gulpパイプをgrep
に詰めて、行のいずれかがd
で始まるかどうかを確認します(ディレクトリがあることを意味します) 。 grep
がその意味のない信頼できないテキストを印刷したくないので、-q
で終了ステータスをチェックして、何かが見つかったかどうかを確認します。そうでない場合は、ディレクトリを作成します(||
または演算子を使用して、最後のコマンドが失敗した場合は次のコマンドを実行します)。 ls
はそれらを?
として出力するため、ファイル名に改行などの恐ろしい文字が含まれている場合でも、これは実際に機能するはずです-すべての行shouldファイルの種類を示す文字で始まるため、おそらく子猫は死なないでしょう。
苦しいfind -exec
呼び出しがあります
前:
$ tree currentDir
currentDir
├── Dir1
│ ├── Dir1
│ │ └── Dir1
│ ├── Dir2
│ └── Dir3
├── Dir2
│ ├── Dir1
│ └── Dir2
│ └── Dir1
└── Dir3
テクスチャディレクトリを作成する
$ find currentDir -depth -type d -exec bash -c 'cd "$1"; shopt -s globstar nullglob; texture=(**/Texture); [[ ${#texture[@]} -eq 0 ]] && mkdir Texture' _ '{}' \;
それに依存します:
-depth
オプションglobstar
シェルオプション_
引数に注意してください。これはbash var $0
に入り、findの現在のパス名はbash var $1
になります。後
$ tree currentDir
currentDir
├── Dir1
│ ├── Dir1
│ │ └── Dir1
│ │ └── Texture
│ ├── Dir2
│ │ └── Texture
│ └── Dir3
│ └── Texture
├── Dir2
│ ├── Dir1
│ │ └── Texture
│ └── Dir2
│ └── Dir1
│ └── Texture
└── Dir3
└── Texture
これは動作するはずです:
shopt -s globstar; for i in **/; do sub=$(find "$i" -type d | wc -l); if [[ "$sub" -eq 1 ]]; then mkdir "$i"/Texture; fi;done
結果:
currentDir
├── Dir1
│ ├── Dir1
│ │ └── Dir1
│ │ └── Texture
│ ├── Dir2
│ │ └── Texture
│ └── Dir3
│ └── Texture
├── Dir2
│ ├── Dir1
│ │ └── Texture
│ └── Dir2
│ └── Dir1
│ └── Texture
└── Dir3
└── Texture
python3 -c 'import os
for d in [root for root, dirs, files in os.walk(".") if not any(dirs)]:
os.mkdir(d + "/Texture")'
そのコマンドはシェルから実行できます。 3行のスクリプトを the Python 3インタープリター に渡し、実行します。スクリプトは、.
(現在のディレクトリ)の下にすべてのディレクトリのリストを作成し、サブディレクトリがまだない各ディレクトリにTexture
サブディレクトリを作成します。
Pythonには、見やすいようにディレクトリを列挙する os.walk
関数があるため、これは他のほとんどのメソッドよりも記述しやすく、理解しやすいです。どのサブディレクトリがあります(より一般的には、Pythonは多くのユーザーがクリーンで直観的に理解できる言語であるため)。
実際にディレクトリを作成するのではなく、作成する新しいディレクトリをshowだけにしたい場合は、 os.mkdir
を置き換えます with print
.これは、コピーして貼り付ける場合の例です。
python3 -c 'import os
for d in [root for root, dirs, files in os.walk(".") if not any(dirs)]:
print(d + "/Texture")'
これらの3行コマンドのいずれかを1行で記述する方法がありますが、必要はありません。対話型のシェルプロンプトで入力または貼り付けて使用するコマンドを入力するか、シェルスクリプトで使用できます。対話形式で入力すると、シェルは2行目と3行目の先頭に>
を出力します($PS2
を別の値に設定していない場合)。それは問題ではありません。
上記では、 Bourne-style Shell を使用していることを前提としています。 bash
、 dash
/ sh
、 ksh
、 zsh
、 posh
など( Thosethreeanswers use shopt -s globstar
。 他のいくつかのシェルにも同様の機能があります 。したがって、それらがあなたのために働くなら、これもそうすべきです。)Ubuntuを使用していて、コマンドを入力しているシェルがわからない場合、 それはbash
です。 csh
または tcsh
を使用している場合、最初の末尾に\
を配置する必要があります。 Unmatched '.
エラーを回避するための2行。?
の代わりに>
が表示されます。
ディレクトリを作成せずに既存のディレクトリ階層でこの方法をテストするには、上記の2番目のコマンドを使用します。ただし、必要に応じて、テスト目的で新しいディレクトリ階層をどこかに作成できます。 mkdir -p dir/{a/{b/c,d,e},f/{g,h/i},j}
は、例のトポロジと同じトポロジのディレクトリツリーを作成します。 find dir -type d -exec touch {}/x \;
にはいくつかのファイルが読み込まれるため、非ディレクトリの存在が問題にならないことを確認できます。 cd dir
に入ります。そして、上記のコマンドと、他の回答に示されているような興味のある他の方法をテストできます。次に、 tree
を実行します。