Como inserir todos os diretórios no caminho atual e executar o script

5

Eu quero entrar em todos os diretórios restaurados pelo comando ls e executar o script.

Eu tentei isso (e muitas outras coisas), mas isso simplesmente não funciona

ls  | awk '{print $1" && pwd"}' | xargs cd

Como fazer isso sem loop?

    
por UAdapter 09.11.2011 / 15:29

7 respostas

8

Se puder, use find como sugerido em outras respostas, xargs é quase sempre para ser evitado.

Mas se você ainda quiser usar xargs , uma alternativa possível é a seguinte:

printf '%s
printf '%s%pre%' */ | xargs -0 -L1 bash -c 'cd -- "$1" && pwd' _
' */ | xargs -0 -L1 bash -c 'cd -- "$1" && pwd' _

Algumas notas:

  1. */ expande para a lista de diretórios na pasta atual, graças à barra final

  2. printf com -L1 (null byte) separa os elementos um para cada linha

  3. a opção xargs to -0 faz com que seja executada uma vez para cada linha de entrada e a opção bash separa a entrada no byte nulo: nomes de arquivos podem conter qualquer caractere, o comando doesn ' Não quebre!

  4. cd remove as aspas duplas e as passa para o script embutido como um único parâmetro, mas -- deve colocar aspas duplas novamente para interpretá-las como uma única string; usar cd torna o comando $0 robusto contra nomes de arquivos que começam com um hífen

  5. para evitar o uso estranho de _ como parâmetro, é comum colocar um primeiro argumento simulado %code%

por enzotib 09.11.2011 / 16:05
14
find . -type d -exec bash -c 'cd "$0" && pwd' {} \;

Troque pwd pelo seu script. E . para o nome do diretório raiz, se não for o diretório "atual".

Você precisa quebrar a cláusula exec em bash -c "..." devido à maneira como -exec funciona. cd não existe em seu ambiente limitado, mas como você pode ver ao executar o comando acima, quando você faz o bash para fazer o trabalho, tudo é executado como previsto.

Editar: não sei por que 2011 Oli não pensou em -execdir , mas essa é provavelmente uma solução mais rápida:

find . -type d -execdir pwd \;
    
por Oli 09.11.2011 / 16:04
2

O comando de localização

O comando find é bastante útil. Ele pode gerar uma lista de arquivos ou diretórios dentro ou abaixo de um diretório especificado e também pode executar um comando em cada item dessa lista de resultados. (Nota: se você estiver usando um sistema multiusuário, certifique-se de ler a seção de considerações de segurança da documentação do Findutils para o comando find.)

As opções para o comando find que precisamos são -tipo d que diz ao find para retornar os nomes de todos os diretórios dentro do caminho especificado, e comando -exec '{}'; que informa para executar o comando nos resultados. Por exemplo:

find /media/music/flac -type d -exec ~/tag-flac-with-rg.sh '{}' \;

Isso diz ao find para retornar todos os diretórios dentro ou abaixo do caminho / media / music / flac e então executar o script tag-flac-with-rg.sh em cada diretório encontrado. O '{}' é substituído por cada nome de diretório encontrado e é passado como um argumento para o script tag-flac-with-rg.sh. O \; marca o final da lista de argumentos para o script tag-flac-with-rg.sh. pode ser que isso ajude você

    
por twister_void 09.11.2011 / 16:05
2

Apenas por curiosidade, tentei dar o seu exemplo e fazê-lo funcionar. Não há razão para usar esta técnica em vez do comando find .

Note: Thanks to enzotib for pointing it out, this does not work for directory names containing spaces or any other characters that make awk think the name consists of several fields.

Para fazer seu exemplo funcionar, alguns ajustes devem ser feitos. Mas primeiro veja o código:

ls -l | grep ^d | awk '{print $NF}' | xargs -n 1 bash -c 'cd $0; ls'

Os dois primeiros comandos garantem que apenas os diretórios sejam listados. Como a listagem ls long contém um d como o primeiro caractere para diretórios, o comando grep seleciona apenas essas linhas.

Com awk , somente a última coluna é exibida em todas as linhas. NF é uma variável incorporada em awk que contém o número máximo de campos. Assim, imprimir $NF exibe o último campo.

Finalmente xargs precisava ser domado para executar o script especificado com apenas um parâmetro por vez. (Eu sei que este tipo de derrota seu propósito.) Caso contrário, o script não pode ser executado para cada diretório sem um loop for .

E para contornar a barreira cd interna, chamamos bash com -c . Observe também que $0 se torna o primeiro parâmetro em vez de $1 .

    
por lgarzo 09.11.2011 / 16:12
2

Talvez dê uma olhada em usar find com -exec ?

    
por Chris Wayne 09.11.2011 / 15:34
2

Outra alternativa:

for directory in *
do
  (cd $directory && awk '{print $1" && pwd"}')
done
    
por Arturo Herrero 20.03.2014 / 15:56
1

Você não deve analisar ls em primeiro lugar.

Você pode usar o GNU find para esse e seu parâmetro -execdir , por exemplo:

find . -type d -execdir realpath "{}" ';'

ou mais exemplos práticos:

find . -name .git -type d -execdir git pull -v ';'

e aqui está a versão com -exec :

find . -type d -print0 | xargs -0 -I% sh -c 'cd "%" && pwd && echo Do stuff'

Para mais exemplos, consulte: Como ir para cada diretório e executar um comando? em SO

    
por kenorb 21.10.2014 / 22:17

Tags