Pergunta

Usando find . -print0 parece ser a única maneira segura de obter uma lista de arquivos em festa devido à possibilidade de nomes de arquivos que contenham espaços, novas linhas, aspas, etc.

No entanto, estou tendo um momento difícil realmente fazer a saída do achado útil dentro bash ou com outros utilitários de linha de comando. A única maneira que eu consegui fazer uso da saída é, canalizando-o para perl, e mudando IFS do Perl como nulo:

find . -print0 | perl -e '$/="\0"; @files=<>; print $#files;'

Este exemplo imprime o número de arquivos encontrados, evitando o perigo de novas linhas em nomes de arquivos corrompendo a contagem, como ocorreria com:

find . | wc -l

Como os programas de linha mais comandos não suportam entrada delimitada por nulo, eu acho que a melhor coisa seria a de capturar a saída de find . -print0 em uma matriz bash, como eu fiz nos perl trecho acima, e, em seguida, continuar com a tarefa , seja ela qual for.

Como posso fazer isso?

Isso não funciona:

find . -print0 | ( IFS=$'\0' ; array=( $( cat ) ) ; echo ${#array[@]} )

Um muito mais geral pergunta pode ser:? Como posso fazer coisas úteis com listas de arquivos em bash

Outras dicas

Talvez você está procurando xargs:

find . -print0 | xargs -r0 do_something_useful

A opção -L 1 poderia ser útil para você também, o que torna xargs exec do_something_useful com o argumento de apenas 1 arquivo.

O principal problema é que o NUL delimitador (\ 0) é inútil aqui, porque não é possível atribuir IFS um NUL valor. Assim como bons programadores tomarmos cuidado, que a entrada para o nosso programa é algo que é capaz de lidar.

Primeiro vamos criar um pequeno programa, que faz esta parte para nós:

#!/bin/bash
printf "%s" "$@" | base64

... e chamá-lo base64str (não se esqueça chmod + x)

Em segundo lugar, podemos agora usar uma simples e direta para-loop:

for i in `find -type f -exec base64str '{}' \;`
do 
  file="`echo -n "$i" | base64 -d`"
  # do something with file
done

Portanto, o truque é, que uma base64-string não tem nenhum sinal que causa problemas para a festança -., Naturalmente, um xxd ou algo lata semelhante também fazer o trabalho

No entanto, uma outra forma de arquivos de contagem:

find /DIR -type f -print0 | tr -dc '\0' | wc -c 

Desde Bash 4.4, o mapfile builtin tem o interruptor -d (para especificar um delimitador, similar ao interruptor -d da declaração read), e o delimitador pode ser o byte nulo. Assim, uma resposta boa para a pergunta no título

Captura de saída de find . -print0 em uma matriz de festa

é:

mapfile -d '' ary < <(find . -print0)

Você pode seguramente fazer a contagem com este:

find . -exec echo ';' | wc -l

(Imprime uma nova linha para cada arquivo / dir encontrado, e depois contar as novas linhas impressas ...)

Evitar xargs se você pode:

man ruby | less -p 777 
IFS=$'\777' 
#array=( $(find ~ -maxdepth 1 -type f -exec printf "%s\777" '{}' \; 2>/dev/null) ) 
array=( $(find ~ -maxdepth 1 -type f -exec printf "%s\777" '{}' + 2>/dev/null) ) 
echo ${#array[@]} 
printf "%s\n" "${array[@]}" | nl 
echo "${array[0]}" 
IFS=$' \t\n' 

Eu sou novo, mas eu acredito que esta uma resposta; espero que ajude alguém:

STYLE="$HOME/.fluxbox/styles/"

declare -a array1

LISTING=`find $HOME/.fluxbox/styles/ -print0 -maxdepth 1 -type f`


echo $LISTING
array1=( `echo $LISTING`)
TAR_SOURCE=`echo ${array1[@]}`

#tar czvf ~/FluxieStyles.tgz $TAR_SOURCE

Este é semelhante à versão de Stephan202, mas os arquivos (e diretórios) são colocados em uma matriz de uma só vez. O loop for aqui é apenas para "fazer coisas úteis":

files=(*)                        # put files in current directory into an array
i=0
for file in "${files[@]}"
do
    echo "File ${i}: ${file}"    # do something useful 
    let i++
done

Para obter uma contagem:

echo ${#files[@]}

velha questão, mas ninguém sugeriu este método simples, então eu pensei que eu iria. Concedida se os seus nomes têm um ETX, isso não resolver o problema, mas eu suspeito que serve para qualquer cenário do mundo real. Tentando usar nulo parece entrar em conflito com IFS padrão manipulação regras. Tempere a seu gosto com as opções de localizar e tratamento de erros.

savedFS="$IFS"
IFS=$'\x3'
filenames=(`find wherever -printf %p$'\x3'`)
IFS="$savedFS"

A resposta de Gordon Davisson é grande para a festança. No entanto, uma exist atalho útil para usuários zsh:

Primeiro, coloque-lhe corda em uma variável:

A="$(find /tmp -type f -print0)"

Em seguida, dividir essa variável e armazená-lo em um array:

B=( ${(s/^@/)A} )

Existe um truque: ^@ é o caractere NUL. Para fazê-lo, você tem que digitar Ctrl + V seguido de Ctrl + @.

Você pode verificar cada entrada de US $ B contém valor correto:

for i in "$B[@]"; echo \"$i\"

leitores atento pode notar que chamada para comando find pode ser evitado na maioria dos casos utilizando a sintaxe **. Por exemplo:

B=( /tmp/** )

Bash nunca foi bom para lidar com nomes de arquivos (ou qualquer texto realmente) porque utiliza espaços como uma lista delimitador.

Eu recomendo usar python com a biblioteca sh .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top