Atravesse todos os subdiretórios e faça algo no shell script do Unix


17

Quero que meu script shell visite todos os subdiretórios em um diretório principal. Faça algo nos diretórios, envie a saída para um arquivo em spool e vá para o próximo diretório. Considere Dir principal = / tmp Sub dir = ABCD (quatro subdiretórios)


2
OK, por favor, mostre seu script até agora. Qual parte está lhe causando problemas?
terdon

Respostas:


22

Use um forloop:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

Ele pesquisa apenas os subdiretórios do diretório /path/to/dir. Observe que o exemplo simples acima falhará se os nomes de diretório contiverem espaços em branco ou caracteres especiais. Uma abordagem mais segura é:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

Ou simplesmente bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(observe que, ao contrário do findque se pensa, também são considerados links simbólicos para diretórios e excluídos os ocultos)


11
pelo menos aponte as limitações e riscos associados ao processamento da saída desse findtipo.
Stéphane Chazelas 27/02

Oi ... eu tentei executar abaixo o loop for d em $ (find / backup / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
Ashish 27/02

Oi ... Eu tentei abaixo para loop. para d em $ (find / backup / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d O resultado esperado é ls -ltr de todos os subdiretórios . O loop acima não está funcionando #
2700 Ashish

1

Sou um bashnovato completo , mas um veterano da UN * X. Embora, sem dúvida, isso possa ser feito nos scripts de shell do Bash, nos velhos tempos costumávamos find [-maxdepth <levels>] <start-dir> -exec <command> ;fazer isso. Você pode fazer uma man findbrincadeira, talvez até que alguém lhe diga como fazê-la bash!


Estou muito lisonjeado por minha resposta "resumida" aqui ter recebido uma votação positiva. No entanto, por que a resposta do @chaos 'abaixo recebeu um voto negativo? (Como um novato neste fórum, não posso postar esse comentário contra a resposta dele, apenas contra a minha.) Sua segunda sugestão está correta para uma solução de script de shell e evita a sobrecarga de executar um findcomando externo .
JonBrave 27/02

Seu segundo é realmente correto. O primeiro falhará se os nomes de diretório contiverem espaços em branco ou caracteres especiais (barras invertidas, por exemplo). Veja a edição que fiz na resposta dele para a versão segura.
terdon

Concordo. Era a segunda resposta que eu estava elogiando.
31415 JonBrave

Eu sei, eu estava apenas explicando o voto negativo (que não fiz).
terdon


1

Parece que você deseja os nomes de arquivos em cada um dos subdiretórios; o ls -l | awknão é suficiente robusta, para o que se esses nomes incluem espaços em branco e / ou novas linhas? O abaixo findfuncionaria mesmo para finds que não têm a -maxdepthoportunidade para eles:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

Eu tenho a solução. O comando find abaixo atende aos meus requisitos.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

Também é possível usar ls, grep e tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du / sed também pode ser usado como seletor se o seu ls não possui as opções acima

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

Pode ser importante observar que esses exemplos retornam diretórios ocultos e excluem os diretórios pai e atual


11
(1)  lsgrava um arquivo por linha (o que a -1opção especifica) por padrão quando a saída padrão é um pipe (portanto, é supérfluo em suas respostas). (2) Analisar a saída de lsé uma péssima idéia - veja isto e isto . Sua primeira resposta falhará se os diretórios tiverem espaços (ou novas linhas) em seus nomes e tudo falhará se eles tiverem novas linhas em seus nomes. (3) Você deve sempre citar variáveis ​​do shell (por exemplo, "$dir") a menos que tenha um bom motivo para não fazê-lo e tenha certeza de que sabe o que está fazendo.
Scott

Bons pontos Scott. Deixando a resposta como, para muitos sistemas sem dirs nomeados de maneira grosseira, acho que ainda pode ser útil para os que estão fora.
JGurtz
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.