Como escrevo um script bash que percorre cada diretório dentro de um diretório parent_executor e executa um comando em cada diretório .
A estrutura de diretórios é a seguinte:
parent_directory (o nome pode ser qualquer coisa - não segue um padrão)
- 001 (os nomes de diretório seguem esse padrão)
- 0001.txt (os nomes dos arquivos seguem esse padrão)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
o número de diretórios é desconhecido.
cd "$d"
seria melhor, pois ele é transferido para situações em que o curinga corresponde a arquivos cujos nomes contêm metacaracteres de espaço em branco e / ou shell.for f in foo bar; do cat "$f"/*.txt; done >output
é funcionalmente equivalente acat foo/*.txt bar/*.txt >output
. No entanto,ls
é um comando que produz resultados ligeiramente diferentes, dependendo de como você passa os argumentos; da mesma forma, umgrep
ouwc
que emita um nome de arquivo relativo será diferente se você o executar em um subdiretório (mas frequentemente, você deseja evitar entrar em um subdiretório precisamente por esse motivo).Esta resposta postada por Todd me ajudou.
Os
\( ! -name . \)
evita a execução do comando no diretório atual.fonte
find FOLDER* -maxdepth 0 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;
-exec bash -c 'cd "$0" && pwd' {} \;
já que alguns diretórios continham aspas simples e duplas.-mindepth 1
pwd
diretamente?disd(){find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c 'cd "{}" && "$@"' \;}
não funciona.Se você estiver usando o GNU
find
, pode tentar o-execdir
parâmetro, por exemplo:ou (conforme comentário do @gniourf_gniourf ):
Nota: Você pode usar em
${0#./}
vez de$0
corrigir./
na frente.ou exemplo mais prático:
Se você deseja incluir o diretório atual, é ainda mais simples usando
-exec
:ou usando
xargs
:Ou exemplo semelhante sugerido por @gniourf_gniourf :
Os exemplos acima suportam diretórios com espaços em seus nomes.
Ou atribuindo ao array bash:
Mude
.
para o nome da sua pasta específica. Se você não precisa executar de forma recursiva, você pode usar:dirs=(*)
em vez. O exemplo acima não suporta diretórios com espaços no nome.Portanto, como sugeriu @gniourf_gniourf , a única maneira adequada de colocar a saída de find em uma matriz sem usar um loop explícito estará disponível no Bash 4.4 com:
Ou não é uma maneira recomendada (que envolve a análise de
ls
):O exemplo acima ignoraria o diretório atual (conforme solicitado pelo OP), mas quebraria os nomes com os espaços.
Veja também:
fonte
find
em uma matriz sem usar um loop explícito estará disponível no Bash 4.4 withmapfile -t -d '' dirs < <(find . -type d -print0)
. Até lá, sua única opção é usar um loop (ou adiar a operação parafind
).dirs
matriz; você poderia loop nafind
saída 's (com segurança) assim:find . -type d -print0 | while IFS= read -r -d '' file; do ...; done
.IFS
,read
, dá a impressão de complexidade adicional. Vou ter que pensar sobre isso, talvez haja alguma maneira mais fácil de fazer isso.IFS
eread
(como você diz) se tornam uma segunda natureza à medida que você se acostuma com eles ... eles fazem parte das formas canônicas e idiomáticas de escrever scripts.find . -type d -execdir echo $(pwd)/{} ';'
não faz o que você quer (o$(pwd)
é expandida antesfind
sequer é executado) ...Você pode conseguir isso canalizando e usando
xargs
. O problema é que você precisa usar o-I
sinalizador que substituirá a substring em seu comando bash pela substring passada por cada um dosxargs
.Você pode substituir
pwd
por qualquer comando que deseja executar em cada diretório.fonte
Se a pasta de nível superior for conhecida, basta escrever algo como isto:
No $ (JOGUE QUANTO QUERER); você pode colocar o código que quiser.
Note que eu não "cd" em nenhum diretório.
Felicidades,
fonte
ls
" aqui - você pode simplesmente fazer issofor dir in $YOUR_TOP_LEVEL_FOLDER/*
.ls $dir
expressãofonte
Enquanto um liners é bom para uso rápido e sujo, eu prefiro a versão mais detalhada abaixo para escrever scripts. Este é o modelo que eu uso, que cuida de muitos casos extremos e permite que você escreva um código mais complexo para executar em uma pasta. Você pode escrever seu código bash na função dir_command. Abaixo, dir_coomand implementa a marcação de cada repositório no git como um exemplo. O restante do script chama dir_command para cada pasta no diretório O exemplo de iteração através de apenas um determinado conjunto de pastas também é incluído.
fonte
Não entendi o que é a formatação do arquivo, já que você só deseja percorrer as pastas ... Você está procurando algo assim?
fonte
você pode usar
procurar todos os arquivos / diretórios no diretório atual recorrente
Do que você pode canalizar a saída, o comando xargs está assim
fonte
fonte
cd
em uma subshell.cd
para que este código não faça nada útil.