
次の構造のディレクトリがあります。
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ファイルを見つけることは非常に簡単であることを知っていますが、それをディレクトリ生成と各検索結果のサブストリングの実行と組み合わせる方法はわかりません。
よろしくお願いします! !
答え1
find example -name \*.txt | sed 's/\.txt$//' | xargs -n 1 mkdir
警告:パスが必要ですいいえ改行文字を含みます。
編集:GNUツールを使用している場合は、terdonの説明を参照してください。
答え2
これには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
。
グローバルスター
**
設定されている場合、パス名拡張コンテキストで使用されるパターンは、すべてのファイルとゼロ以上のディレクトリとサブディレクトリと一致します。パターンの後に行くと、/
ディレクトリとサブディレクトリのみが一致します。
したがって、を使用して有効にした後、shopt -s globstar
このモードは**/*.txt
名前で終わるすべてのファイル(またはディレクトリ)を検索します.txt
。
シェル構文は、${i%.txt}
部分文字列を削除するために使用されます。一般的な形式は、変数の末尾から最初のインスタンスを削除${variable%string}
することです。string
したがって、${i%.txt}"
ファイル名(親ディレクトリを含む)からを引いた値になります.txt
。したがって、これを[に渡すと、mkdir
希望のディレクトリが作成されます。
個人的には上記の構文がより簡単だと思いますが、使用方法は次のとおりですfind
。
find . -name '*.txt' -exec sh -c 'mkdir ${0%.txt}' {} \;
ここで各結果を-exec command {}
置き換えてから実行してみてください。ここのコマンドはへの呼び出しなので、0番目の位置引数として使用されます。したがって、上記と同じシェル置換を実行してディレクトリを作成します。{}
find
command
sh -c
sh
{}
$0