web-dev-qa-db-ja.com

mkdirと部分文字列で検索

次の構造のディレクトリがあります。

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ファイルを見つけるのは非常に簡単ですが、それをディレクトリの作成やすべての検索結果の部分文字列の実行と組み合わせる方法を理解できないことを理解しています。

前もって感謝します!!

2
i474232898

これには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として取ります。そのため、上記で説明したのと同じシェル置換を実行して、ディレクトリを作成します。

3
terdon
find example -name \*.txt | sed 's/\.txt$//' | xargs -n 1 mkdir

警告:これには、パスに改行が含まれている必要がありますnot

編集:GNUツールを使用している場合は、terdonのコメントを参照してください。

4
kmkaplan