次のディレクトリ構造があるとします。
base/
|
+-- app
| |
| +-- main
| |
| +-- sub
| |
| +-- first
| | |
| | +-- tib1.ear
| | \-- tib1.xml
| |
| \-- second
| |
| +-- tib2.ear
| \-- tib2.xml
ファイルの相対パスの1つear
ですbase/app/main/sub/first/tib1.ear
。次の部分文字列を抽出するにはどうすればよいですか?
- ファイル
tib1.ear
またはtib2.ear
- ファイルの背後にあるサブディレクトリ(ファイルを除く)
base/app/
、main/sub/first
つまりmain/sub/second
すべてのディレクトリ名は動的に生成されるため、不明なので、base/app/
単に既知の部分文字列の長さを取得してcut
切り取ることはできませんが、ファイル名がわかっている場合はこれがどのように可能かを知っています。異なる結果の長さに応じて、複数の文字列を切り取り、連結するよりも簡単な方法があると思います。
これに似た正規表現マジックを見た記憶があります。これにはバックスラッシュを使用して部分文字列を分割して連結することが含まれますが、残念ながらどのように行ったのか、どこで見て再び見つけたのか覚えていません。
答え1
ファイル名から始めましょう。
$ f=base/app/main/sub/first/tib1.ear
基本名を抽出するには:
$ echo "${f##*/}"
tib1.ear
ディレクトリ名の必須部分を抽出するには、次のようにします。
$ g=${f%/*}; echo "${g#base/app/}"
main/sub/first
${g#base/app/}
そして${f##*/}
はいプレフィックスの削除。 ${f%/*}
はいサフィックスの削除。
文書
からman bash
:
${parameter#word} ${parameter##word} Remove matching prefix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``#'' case) or the longest matching pattern (the ``##'' case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list. ${parameter%word} ${parameter%%word} Remove matching suffix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``%'' case) or the longest matching pattern (the ``%%'' case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable sub‐ scripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.
代替
basename
ユーティリティと以下を考慮することもできますdirname
。
$ basename "$f"
tib1.ear
$ dirname "$f"
base/app/main/sub/first
答え2
テストファイルの生成
mkdir -p base/app/main/sub/{first,second}
touch base/app/main/sub/first/tib1.{ear,xml}
touch base/app/main/sub/second/tib2.{ear,xml}
Bashを使ってEarファイルを探す
shopt -s globstar nullglob
ear_files=( base/**/*.ear )
printf "%s\n" "${ear_files[@]}"
base/app/main/sub/first/tib1.ear
base/app/main/sub/second/tib2.ear
配列を繰り返し、John1024の回答を使用して各パスから必要な情報を抽出します。
for f in "${ear_files[@]}"; do ...; done