Iterando sobre cada linha de saída ls -l

119

Quero iterar em cada linha na saída de: ls -l /some/dir/*

Agora estou tentando: for x in $(ls -l $1); do echo $x; done

No entanto, isso itera sobre cada elemento da linha separadamente, então eu obtenho:

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:07
File1

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:17
File2

Mas eu quero iterar em cada linha como um todo. Como faço isso?

Ivan
fonte
1
Sempre cite as variáveis ​​(e a saída do comando), a menos que você tenha um motivo específico para não fazê-lo.
glenn jackman

Respostas:

246

Defina IFS como nova linha, assim:

IFS='
'
for x in `ls -l $1`; do echo $x; done

Coloque um sub-shell em torno dele se você não quiser definir o IFS permanentemente:

(IFS='
'
for x in `ls -l $1`; do echo $x; done)

Ou use enquanto | leia em vez disso:

ls -l $1 | while read x; do echo $x; done

Mais uma opção, que executa o while / read no mesmo nível de shell:

while read x; do echo $x; done << EOF
$(ls -l $1)
EOF
Randy Proctor
fonte
12
Cuidado ao canalizar para while, o while será executado em um subshell, o que significa que não pode alterar as variáveis ​​no processo principal
Reorx
1
O que $ 1 está fazendo aqui? Preciso usar isso em um script que estou escrevendo que aceita argumentos. O $ 1 está jogando coisas fora. O que posso colocar lá em vez de $ 1 para obter o mesmo efeito? Eu gostaria de usar a segunda solução.
noob-in-need
@ noob-in-need Substitua pelo diretório que você deseja listar
vpzomtrrfrt
1
Você pode querer fazer read -rou então o bash removerá as barras invertidas sem escape dos dados.
Brian Gordon de
6

Depende do que você deseja fazer com cada linha. awk é um utilitário útil para esse tipo de processamento. Exemplo:

 ls -l | awk '{print $9, $5}'

.. em meu sistema imprime o nome e o tamanho de cada item do diretório.

Adam Holmberg
fonte
3

Como já foi mencionado, o awk é a ferramenta certa para isso. Se você não quiser usar o awk, em vez de analisar a saída de "ls -l" linha por linha, você pode iterar em todos os arquivos e fazer um "ls -l" para cada arquivo individual assim:

for x in * ; do echo `ls -ld $x` ; done
Axel
fonte
3

Você também pode tentar o findcomando. Se você deseja apenas arquivos no diretório atual:

find . -d 1 -prune -ls

Executar um comando em cada um deles?

find . -d 1 -prune -exec echo {} \;

Contar linhas, mas apenas em arquivos?

find . -d 1 -prune -type f -exec wc -l {} \;

David Koski
fonte
encontrar está quebrado. Freqüentemente, recebo algumas mensagens de erro bizarras. ele quer me ajudar quando a linha de comando é perfeitamente válida, e parece que uma vez que começar a fazer isso, não irá parar até a próxima reinicialização TALVEZ. às vezes parece de natureza aleatória em relação aos erros. não tenho certeza de como posso relatar o bug.
Jim Michaels de
1

O utilitário read (1) junto com o redirecionamento de saída do comando ls (1) fará o que você quiser.

Steve Emmerson
fonte
-1

Então, por que ninguém sugeriu apenas usar opções que eliminam as partes que ele não quer processar.

No Debian moderno, você apenas obtém seu arquivo com:

ls --format=single-column 

Além disso, você não precisa prestar atenção em qual diretório está executando-o se usar o diretório completo:

ls --format=single-column /root/dir/starting/point/to/target/dir/

Estou usando este último comando acima e obtenho a seguinte saída:

bot@dev:~/downloaded/Daily# ls --format=single-column /home/bot/downloaded/Daily/*.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141119_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141120_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141121_IENT1.txt.gz
BradChesney79
fonte