Extrair o caminho do subdiretório do diretório parcialmente conhecido

3

Digamos que eu tenha a seguinte estrutura de diretórios:

base/
|
+-- app
|   |
|   +-- main
|       |
|       +-- sub
|           |
|           +-- first
|           |   |
|           |   +-- tib1.ear
|           |   \-- tib1.xml
|           |
|           \-- second
|               |
|               +-- tib2.ear
|               \-- tib2.xml

Um dos caminhos relativos para um arquivo ear seria base/app/main/sub/first/tib1.ear , como eu poderia extrair as subseqüências para:

  • O arquivo, tib1.ear ou tib2.ear
  • O subdiretório após base/app/ , mas não incluindo o arquivo, sendo main/sub/first ou main/sub/second

Todos os nomes de diretório são gerados dinamicamente, então eu não os conheço além de base/app/ e, portanto, não posso simplesmente usar os comprimentos das sub-strings conhecidas e usar cut para truncá-los; mas vejo como isso poderia ser possível uma vez que os nomes dos arquivos sejam conhecidos. Eu sinto que há uma maneira mais fácil do que cortar e unir um monte de strings com base na duração de outros resultados.

Eu lembro de ter visto alguma mágica de expressão regular para algo semelhante a isso. Tratou de dividir e unir os substrings com barras invertidas, mas, infelizmente, não me lembro como eles fizeram isso ou onde eu vi aqui para procurar novamente.

    
por Darrel Holt 15.09.2017 / 21:58

2 respostas

5

Vamos começar com o nome do seu arquivo:

$ f=base/app/main/sub/first/tib1.ear

Para extrair o nome base:

$ echo "${f##*/}"
tib1.ear

Para extrair a parte desejada do nome do diretório:

$ g=${f%/*}; echo "${g#base/app/}"
main/sub/first

${g#base/app/} e ${f##*/} são exemplos de remoção de prefixo . ${f%/*} é um exemplo de remoção do sufixo .

Documentação

De 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.

Alternativas

Você também pode considerar os utilitários basename e dirname :

$ basename "$f"
tib1.ear
$ dirname "$f"
base/app/main/sub/first
    
por 15.09.2017 / 22:09
1

criando os arquivos de teste

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}

encontrando os arquivos de ouvido com o bash

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

Itere sobre o array e use a resposta de John1024 para extrair as informações necessárias de cada caminho.

for f in "${ear_files[@]}"; do ...; done
    
por 16.09.2017 / 14:55