Como posso encontrar, recursivamente, todos os arquivos em minha árvore de diretórios que o primeiro caractere na primeira linha de cada arquivo é um espaço, uma tabulação ou uma quebra de linha?

0

por exemplo:

Eu tenho dois arquivos, a.txt e b.txt:

a.txt

line 1
line 2

b.txt

 line 1
line 2

Nesse caso, b.txt deve aparecer na listagem porque o primeiro caractere da primeira linha é um espaço, uma tabulação ou uma quebra de linha.

    
por Lawrence 27.02.2018 / 13:16

4 respostas

0

O caminho certo com o comando find + awk :

find . -type f -size +0c -exec awk '{ exit (/^[[:space:]]/? 0 : 1) }' {} \; -print

The exit statement causes awk to immediately stop executing the current rule and to stop processing input; any remaining input is ignored. The exit statement is written as follows:

exit [return code]

If an argument is supplied to exit, its value is used as the exit status code for the awk process

A ação

find -print será executada somente se awk processar fornecer status de saída 0

Uma abordagem mais simplificada seria a seguinte:

find . -type f -size +0c -exec awk '{ exit (!NF? 0 : 1) }' {} \; -print
    
por 27.02.2018 / 13:30
1

Tente isto:

find . -type f -exec awk 'NR==1 && /^\s/{print FILENAME}' {} \;

Ou usando 4:

shopt -s globstar
awk 'NR==1 && /^\s/{print FILENAME} **/*
    
por 27.02.2018 / 13:21
1

com zsh :

starts_with_space() {
  local c
  read -ku0 c < ${1-$REPLY} && [[ $c = [$' \t\n'] ]]
}
printf '%s\n' **/*(D.L+0+starts_with_space)
  • D inclui arquivos de pontos (arquivos ocultos) e desce para diretórios ocultos como find .
  • . apenas arquivos regulares (como find ' -type f )
  • L+0 : somente arquivos não vazios (como find ' -size +0c )
  • +starts_with_space apenas aqueles para os quais starts_with_space retorna verdadeiro.

Um dos benefícios sobre find é que ele fornece uma lista classificada de nomes de arquivos. Ele só lê um caractere (possivelmente mais de um byte em locales com conjuntos de caracteres de múltiplos bytes) de cada arquivo.

    
por 27.02.2018 / 13:46
0

Solução com awk no final.

Usando o GNU sed (que suporta a saída do script sed com um status de saída explícito):

find . -type f -size +0c -exec sed -n '1{/^[^[:blank:]]/q 1};q' {} ';' -print

O -size +0c garante que os arquivos completamente vazios não sejam reportados.

Se o diretório atual contiver os dois arquivos da pergunta e um arquivo extra c.txt com uma primeira linha vazia, isso gerará

./b.txt
./c.txt

O script sed do GNU:

1{
    /^[^[:blank:]]/q 1
}
q

Para a linha 1, ele verifica se o primeiro caractere na linha não é em branco (não é espaço ou tabulação) e, se estiver, sairá com o status de saída 1 ( q 1 ). Caso contrário, ele sai com o status de saída zero (o último q ).

Uma primeira linha vazia não corresponderá a /^[^[:blank:]]/ , de modo que o caso seja tratado corretamente.

Se sed sair com um status de saída zero, o -print fará com que o nome do caminho do arquivo seja impresso na saída padrão por find .

O equivalente, mas usando awk (qualquer awk serve):

find . -type f -size +0c -exec awk '/^[^[:blank:]]/ { e=1 } { exit e }' {} ';' -print
    
por 27.02.2018 / 15:10