web-dev-qa-db-ja.com

コマンドラインを使用して最後のディレクトリにディレクトリを再帰的に作成するにはどうすればよいですか?

ディレクトリの名前が重要でない次のディレクトリ構造があるとしましょう。

currentDir/
   Dir1
      Dir1
         Dir1 *
      Dir2 *
      Dir3 *
   Dir2
      Dir1 *
      Dir2 
         Dir1*
   Dir3*

ツリーブランチの最後のディレクトリのみに「Texture」という名前のディレクトリを作成できる方法はありますか(例では*でマークされています)。これらのディレクトリのみがTextureディレクトリを取得し、他のディレクトリは取得しないようにします。

すべてのディレクトリにはファイルがある場合とない場合がありますが、エンドディレクトリには他のディレクトリはありません。

5
kingcobra1986

最初に再帰的グロビングをオンにします

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ファイルの種類を示す文字で始まるため、おそらく子猫は死なないでしょう。

6
Zanna

苦しい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' _ '{}' \;

それに依存します:

  • 深さ優先ナビゲーションを有効にするfindの-depthオプション
  • 再帰的なファイルパターンマッチングを有効にするbashの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
5
glenn jackman

これは動作するはずです:

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
3
George Udosen

Python はこれを簡単にします。

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 を使用していることを前提としています。 bashdash / shkshzshposh など( 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 を実行します。

1
Eliah Kagan