
Atualmente tenho este comando, que imprime com sucesso cada nome de arquivo em sua própria linha:
find . -exec echo {} \;
Estou tentando dividir a lógica para que o find
comando execute uma função. Baseado emessa questãoEu tentei isso:
my_function() {
echo $1
}
export -f my_function
find . -exec bash -c 'my_function "$@"' bash {} +
Então recebo esta saída:
.
Também tentei substituir $@
por, $*
mas isso faz com $1
que todos os arquivos fiquem sem quebras de linha. Eu gostaria de executar uma lógica que verificasse cada arquivo, então gostaria $1
de ser apenas um arquivo por vez. Tentei dividir a saída com espaços, for file in $1
mas isso não funciona para arquivos que possuem espaços no nome do arquivo. Como executo uma função Bash para cada arquivo encontrado pelo find
comando?
EDIT: Aqui está todo o script que estou usando. Parece funcionar bem.
# Ensures that non-csproj text files are formatted with LF line endings.
format() {
for pathname do
if [[ $pathname == *"git"* ]]; then
continue
elif [[ $pathname == *"csproj"* ]]; then
continue
fi
dos2unix $pathname
done
}
export -f format
find . -exec bash -c 'format "$@"' bash {} \;
Responder1
Para executar dos2unix --newline
em todos os arquivos regulares dentro e abaixo do diretório atual, evitando qualquer arquivo cujo nome contenha a string git
:
find . -type f ! -name '*git*' -exec dos2unix --newline {} +
Ou seja, encontre todos os arquivos regulares cujos nomes não correspondam ao padrão *git*
e execute dos2unix --newline
todos eles em lotes tão grandes quanto possível de uma só vez. Mude ! -name '*git*'
para ! -path '*git*'
para evitar qualquer arquivo cujo caminho contenha a string git
(por exemplo, arquivos em .git
diretórios).
Para evitar explicitamente quaisquer .git
diretórios, mas para incluir qualquer outra coisa que possa ter git
em seu nome:
find . -name .git -prune -o -type f -exec dos2unix --newline {} +
Isso impede find
até mesmo que você entre em qualquer diretório chamado .git
usando -prune
para excluir esses caminhos da árvore de pesquisa.
Responda antes de editar a pergunta:
Sua função imprime apenas o primeiro argumento. O ponto é o caminho de pesquisa de nível superior que você usa com o find
. Ele é aprovado porque você não faz nenhuma filtragem específica das entradas do diretório (como, por exemplo, -type f
apenas para arquivos regulares, ou -name
, ou qualquer outro tipo de find
teste).
Se você quiser que sua função imprima cada um de seus argumentos, use
my_function() {
printf '%s\n' "$@"
}
que permite printf
imprimir cada um dos argumentos com uma nova linha no meio, ou
my_function() {
for pathname do
printf '%s\n' "$pathname"
done
}
que percorre os argumentos e chama printf
uma vez para cada um.
Espera-se que isso funcione corretamente se você chamar a função como
my_function "$@"
de dentro do seu script in-line bash -c
. O "$@"
expande-se para todos os argumentos dados ao script, citados individualmente.
Outra maneira seria mover o loop para o bash -c
script:
for pathname do
my_function "$pathname"
done
e então ter
my_function () {
printf '%s\n' "$1"
}
Isso seria explicitamente fazer o que você diz que gostaria de fazer, ou seja, chamar a função uma vez para cada nome de caminho.
O find
comando seria então parecido com
find . -exec bash -c 'for pathname do my_function "$pathname"; done' bash {} +
ou, possivelmente um pouco mais legível,
find . -exec bash -c '
for pathname do
my_function "$pathname"
done' bash {} +
Isto seria, aliás, o mesmo que
shopt -s globstar nullglob dotglob
for pathname in ./**/*; do
my_function "$pathname"
done
exceto que .
não seria processado. Usando isso, você não precisaria exportar sua my_function
função.
Com o loop dentro da função (como nos dois primeiros trechos de código desta resposta), isso seria abreviado para
shopt -s globstar nullglob dotglob
my_function ./**/*