Em um script que eu uso find
para coletar alguns arquivos no diretório atual, como em
$ find . -name "*.h"
./foo.h
Agora eu gostaria que fosse apenas saída foo.h
, sem o ./
prefixo. Eu pensei que a seqüência vazia ""
denotava o diretório atual em comandos shell. Mas isso dá:
$ find "" -name "*.h"
find: ftsopen: No such file or directory
Então eu estava errado. Agora, minha pergunta é quando / como / onde / .. uma "string vazia (?)" Indica o diretório atual em comandos que esperam um nome de arquivo ou nome de caminho? Existe uma explicação clara e esclarecedora?
Uma questão paralela é se a busca detalhada acima pode ser resolvida de maneira simples, sem a manipulação de strings a la ${parameter#word}
ou cut
or sed
?
find
possui o parâmetro -printf para manipular como os resultados são mostrados.find . -name '*.h' -printf '%P\n'
irá remover o./
prefixo. Veja o quefind . -name '*.h' -print
faz.-printf
opção. FWIW,strings
na minha descoberta dá@(#)PROGRAM:find PROJECT:shell_cmds-175
?!?Respostas:
Há muito tempo (na 7ª edição , 32V , 4.2BSD , 4.3BSD ), no nível de chamada do sistema, um nome de caminho com comprimento zero denotava o diretório de trabalho atual (quando usado para pesquisa; era proibido ao tentar criar ou excluir um arquivo ou diretório). No Sistema III , foi um erro usar um nome de caminho de tamanho zero em todas as circunstâncias, e o padrão POSIX tem isso a dizer sobre a resolução do nome de caminho:
fonte
dir/
é principalmente o mesmo quedir/.
Você pode usar:
Observe que os arquivos no diretório atual cujo nome começa com
.
serão omitidos e os arquivos cujo nome começa com-
serão interpretados como opçõesfind
e causam estragos, portanto, isso não é um equivalente geral afind . …
.A ausência de uma sequência terminada em "
/
" como parte de um nome de arquivo implica o diretório atual, mas isso não significa que o diretório atual seja indicado por uma sequência vazia (que não pode ser a mesma que a ausência de uma sequência, embora possa parecer o mesmo quando impresso).fonte
Em geral, a cadeia vazia não indica o diretório atual, nem para shell comandos nem nas chamadas do sistema. Isso ocorreu em alguns sistemas mais antigos, mas não em sistemas compatíveis com POSIX .
Ocasionalmente, você encontrará um programa que usa o diretório atual quando passa uma string vazia e o programa espera um nome de diretório. Isso às vezes é deliberado e, às vezes, um efeito colateral de preceder o caminho absoluto do diretório atual quando a sequência especificada não inicia com uma barra.
A melhor coisa para você seria deixar o
./
. Não faz mal nenhum.Se a lista de arquivos for para
Observe que isso controla alguns nomes de arquivos que contêm novas linhas. Isso geralmente não é um problema para o consumo humano, e a saída de
find
não é adequada para o consumo do programa, pois é ambígua. Se você estiver usando-print0
, o que é adequado para o consumo do programa, provavelmente não se importa com o./
prefixo.Você pode usar em
find * …
vez defind . …
, mas observe quefind *
há vários defeitos que o tornam inadequado em geral:.
é omitido..
ou ..`) são omitidos.-
(ou um arquivo chamado!
ou(
...), ele será interpretado como uma opção ou predicado porfind
.O primeiro ponto não importa se o seu filtro exclui o diretório atual. Para o segundo ponto, você pode usar os padrões
..?* .[!.]* *
para corresponder a todos os arquivos no diretório atual, mas precisará verificar se cada padrão corresponde a pelo menos um arquivo e omitir se não corresponder. Isso é possível, mas muito complicado. O último ponto é uma rolha. Portanto,find *
pode ser adequado para o uso rápido da linha de comando, mas não o use em um script.Uma abordagem alternativa é usar o recurso de globbing recursivo da concha, por exemplo
Isso precisa ser ativado
shopt -s globstar
no bash eset -o globstar
no ksh93 e não existe em um shell POSIX básico, como o dash. Arquivos de ponto não serão percorridos por padrão; Para incluí-los, faça com que o globbing não ignore os arquivos de pontoshopt -s dotglob
no bash ouFIGNORE='@(.|..)'
no ksh93. Além disso, se não houver correspondências, esse comando imprime o padrão; executeshopt -s nullglob
no bash para imprimir uma linha vazia e use o padrão~(N)**/*.h
no ksh.No zsh, o globbing recursivo está ativado por padrão. Use o qualificador glob
D
para incluir arquivos de ponto eN
imprimir uma linha vazia se não houver correspondências (por padrão, o zsh gera um erro se um padrão não corresponder a nenhum arquivo). Você pode usarprintf
como acima oufonte
find *
são novos para mim e alguns são assustadores!Não consigo pensar em nenhum exemplo em que a cadeia vazia denote o diretório atual
.
. Você pode estar pensando em invocações comols
, mas isso ocorre porquels
assume o diretório atual se nenhum parâmetro for fornecido e, na verdade, ele não aceitará a string vazia:fonte
PATH
componente.Existem vários truques que você pode usar para obter a saída do find sem o líder
./
:Use a
-printf
opção encontrar e diga para imprimir apenas%f
. Vejaman find
:Por exemplo:
Analise a saída:
@ Truque de Anthon
Quanto à sua outra pergunta, a cadeia vazia nunca indica o diretório atual. É apenas que vários programas tomam o diretório atual como padrão; portanto, quando você os executa sem argumentos, eles são executados no diretório atual.
fonte
find
. Ou use%P
apenas para retirar o./
find * -name '*.h'
irá encontrarfoo/.bar.h
, mas não.bar.h
no diretório atual.Se os arquivos estiverem no diretório atual, você pode apenas usar
ls
:Se você quiser os arquivos nos subdiretórios também e apenas precisar do nome do arquivo, faça algo como:
Existem comandos que obterão a ausência de uma string como o diretório atual, mas basicamente porque eles obterão o diretório atual como padrão se nada for inserido. O
.
sempre denotar a dir atual (e..
o diretório pai)fonte
find
solução remove todos os componentes do diretório