次の構造のディレクトリがあります。
example
├───1
│ └───01-01-2015.txt
├───2
│ └───02-02-2016.txt
├───3
│ └───03-03-2017.txt
└───script.sh
すべての.txtファイルを検索し、そのほかに特定のフォルダー内の.txtファイルの名前に基づいた名前の新しいフォルダーを作成するスクリプトを作成しようとしています。
したがって、結果は次のようになります。
example
├───1
│ ├───01-01-2015
│ └───01-01-2015.txt
├───2
│ ├───02-02-2016
│ └───02-02-2016.txt
├───3
│ ├───03-03-2017
│ └───03-03-2017.txt
└───script.sh
したがって、フォルダ「3」サブフォルダ「03-03-2017」、フォルダ「2」サブフォルダ「02-02-2016」などにあります。
すべての.txtファイルを見つけるのは非常に簡単ですが、それをディレクトリの作成やすべての検索結果の部分文字列の実行と組み合わせる方法を理解できないことを理解しています。
前もって感謝します!!
これにはbashループを使用します。
for i in **/*.txt; do mkdir "${i%.txt}"; done
あなたの例でこれを実行すると、次のようになります。
$ tree
.
├── 1
│ └── 01-01-2015.txt
├── 2
│ └── 02-02-2016.txt
└── 3
└── 03-03-2017.txt
3 directories, 3 files
$ shopt -s globstar
$ for i in **/*.txt; do mkdir "${i%.txt}"; done
terdon@oregano foo $ tree
.
├── 1
│ ├── 01-01-2015
│ └── 01-01-2015.txt
├── 2
│ ├── 02-02-2016
│ └── 02-02-2016.txt
└── 3
├── 03-03-2017
└── 03-03-2017.txt
6 directories, 3 files
globstar
はbashオプションであり、man bash
で説明されています。
globstar
設定されている場合、パス名拡張コンテキストで使用されるパターン
**
は、すべてのファイルと0個以上のディレクトリおよびサブディレクトリに一致します。パターンの後に/
が続く場合、ディレクトリとサブディレクトリのみが一致します。
したがって、shopt -s globstar
で有効にした後、パターン**/*.txt
は、名前が.txt
で終わるすべてのファイル(またはdir)を検索します。
${i%.txt}
は、部分文字列を削除するためのシェル構文です。一般的な形式は${variable%string}
で、変数の末尾からstring
の最初のインスタンスを削除します。したがって、${i%.txt}"
は、ファイル名(親ディレクトリを含む)から.txt
を引いたものになります。したがって、[それをmkdir
に渡すと、必要なディレクトリが作成されます。
個人的には、上記の構文ははるかに単純だと思いますが、find
を使用してそれを行う方法は次のとおりです。
find . -name '*.txt' -exec sh -c 'mkdir ${0%.txt}' {} \;
ここで、-exec command {}
は{}
をfind
の各結果に置き換えてから、command
を実行します。ここでのコマンドはsh -c
の呼び出しであるため、sh
は{}
をゼロ番目の位置パラメーター$0
として取ります。そのため、上記で説明したのと同じシェル置換を実行して、ディレクトリを作成します。
find example -name \*.txt | sed 's/\.txt$//' | xargs -n 1 mkdir
警告:これには、パスに改行が含まれている必要がありますnot。
編集:GNUツールを使用している場合は、terdonのコメントを参照してください。