部分的に既知のディレクトリからサブディレクトリパスを抽出する

部分的に既知のディレクトリからサブディレクトリパスを抽出する

次のディレクトリ構造があるとします。

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

関連情報