Eu preciso encontrar um arquivo * .sh do meu diretório e subdiretórios e exibi-los sem Full Path

0
find . -iname "*.sh" | sed 's/[.]sh$//'
./backup/samukano/ex04/who_am_i
./backup/samukano/ex05/people
./days/day01/samukano/ex01/print_groups
./days/day01/samukano/ex02/find_sh
./samukano/ex04/who_am_i
./samukano/ex05/people

E eu preciso apenas

who_am_i
people
...
people
    
por Saken 04.09.2018 / 10:42

2 respostas

1

find . -iname "*.sh" -exec basename {} \; | sed s/\.sh//g 

O utilitário basename remove todas as informações do diretório de um caminho - relativo ou absoluto.

O utilitário dirname faz o oposto, se necessário.

    
por 04.09.2018 / 14:39
0

tl; dr

Portátil, não robusto:

find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) |
sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'

Robusto, para analisar sequências com terminação nula:

find . -type f -iname "*.sh" -printf "%f
find . -type f -iname "*.sh" -printf "%f
find . -type f -iname "*.sh" -printf "%f
find . -type f -iname "*.sh" -printf "%f
foo
bar
" | sed -z 's/[.][sS][hH]$/\n/'
" | sed -z 's/[.][sS][hH]$//'
" | sed -z 's/[.][sS][hH]$/\n/'
" | sed -z 's/[.][sS][hH]$//'

Internamente robusto com saída possivelmente ambígua, para visualização:

find . -type f -iname "*.sh" -exec basename -z -a {} + | sed -z 's/[.][sS][hH]$//'

Resposta completa

Existem muitas maneiras, algumas mais robustas que outras. Além disso, as ferramentas que você pode usar têm habilidades sobrepostas, muitas delas não são POSIX, então você pode ou não ter as opções necessárias.

Além disso, qualquer diretório de nome de arquivo pode conter novas linhas e outros caracteres estranhos. Por esse motivo, para analisar nomes de arquivos de maneira robusta, você gostaria de tratá-los como sequências com terminação nula.

Em seguida, talvez você queira imprimir o resultado como strings terminadas por nova linha (ou seja, regulares), de qualquer forma, para legibilidade humana (embora apresente resultados ambíguos).

Ferramentas geralmente suportam strings terminadas em null com extensões não POSIX.

Por exemplo para se livrar desses caminhos completos que são o principal problema, você pode usar:

  • find . -printf "%f" , mas seu find pode ou não suportar -printf ;
  • ou basename ;
  • ou até sed .

Para remover .sh , você pode usar:

  • basename path_to_process .sh , mas diferencia maiúsculas de minúsculas e eu acho que você usou -iname por uma razão (nota -iname não é requerida pelo POSIX);
  • ou sed (como você fez), o que pode tornar insensíveis a maiúsculas e minúsculas.

Esta análise não é exaustiva.

A versão mais robusta e insensível a maiúsculas retorna cadeias terminadas em nulo. Isso torna a saída totalmente confiável para análise adicional:

find . -type f -iname "*.sh" -exec basename -z {} \; | sed -z 's/[.][sS][hH]$//'

O mesmo, retornando uma saída legível e possivelmente ambígua:

find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) ...

A ambiguidade se manifesta assim:

find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) |
sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'

Havia dois scripts: foo.sh e bar.sh ? ou apenas um foo(newline here)bar.sh ?

Ele ficará ainda mais confuso se você não puder usar sed -z e deve fornecer entrada para sed como sequências terminadas por nova linha. Nesse caso, um único arquivo foo.sh(newline here)bar.sh também gerará a saída acima.

E se o seu sed suportar -z mas find não suportar -printf ? Talvez seu basename suporte -z . Isso deve ser totalmente robusto:

find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) |
sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'

ou sem o suporte para -a :

find . -type f -iname "*.sh" -printf "%f
find . -type f -iname "*.sh" -printf "%f
find . -type f -iname "*.sh" -printf "%f
find . -type f -iname "*.sh" -printf "%f
foo
bar
" | sed -z 's/[.][sS][hH]$/\n/'
" | sed -z 's/[.][sS][hH]$//'
" | sed -z 's/[.][sS][hH]$/\n/'
" | sed -z 's/[.][sS][hH]$//'

Eu posso ver que seu find suporta -iname , mas talvez não. E se isso não aconteceu? Abordagem bastante ingênua, mas de trabalho:

find . -type f -iname "*.sh" -exec basename -z -a {} + | sed -z 's/[.][sS][hH]$//'

Como você pode ver, tudo depende das opções disponíveis.

Finalmente, vamos supor que seus caminhos usem um conjunto seguro de caracteres imprimíveis (sem novas linhas, etc.). Este comando deve ser portátil e bom o suficiente:

find . -type f -iname "*.sh" -exec basename -z {} \; | sed -z 's/[.][sS][hH]$//'
    
por 04.09.2018 / 14:56

Tags