$ find -exec cd = erro: = find: ‘cd’: nenhum arquivo ou diretório

7

Quando executo este comando, ele funciona:

$ find . -inum 888696 -exec ls '{}' \;
Conversation.pst  Outlook Data File  Outlook Data File.sbd  Trash      Unsent Messages
Inbox.pst     Outlook Data File.msf  Sent.pst       Trash.msf  Unsent Messages.msf

No entanto, ao substituir ls por cd , não funciona:

$ find . -inum 888696 -exec cd '{}' \;
find: ‘cd’: No such file or directory

Eu sei que cd é bash integrado, então tentei o seguinte, o que não funciona:

$ find . -inum 888696 -exec builtin cd '{}' \;
find: ‘builtin’: No such file or directory

Como posso usar o cd juntamente com o comando find -exec ?

UPDATE

A razão pela qual eu estou tentando usar cd com find -exec é que o nome do diretório é um nome estranho que aparece no meu terminal como algo como ???? .

    
por user3405291 05.06.2018 / 13:17

5 respostas

15

A opção -exec para find executa um utilitário externo, possivelmente com alguma opção de linha de comando e outros argumentos.

Seu Unix não fornece cd como um utilitário externo, apenas como um shell embutido, então find falha em executá-lo. Pelo menos o macOS e o Solaris do fornecem cd como um utilitário externo.

Haveria pouco ou nenhum uso para executar cd dessa maneira, exceto como uma forma de testar se o nome do caminho encontrado por find é um diretório no qual você seria capaz de cd . O diretório de trabalho no seu shell interativo (ou o que estiver chamando find ) não mudaria de qualquer maneira.

Relacionados:

Se você estiver com problemas com o nome de um diretório sendo estranho ou extremamente difícil de digitar e quiser mudar para esse diretório, considere criar um link simbólico para o diretório e, em seguida, cd usando esse link :

find . -inum 888696 -exec ln -s {} thedir ';'

Isso criaria um link simbólico chamado thedir que apontaria para o diretório problemático. Você pode então mudar o diretório de trabalho com

cd thedir

(se o link existir no diretório atual). Isso evita modificar o diretório de qualquer maneira. Outra ideia seria renomear o diretório de maneira semelhante com find , mas isso não seria aconselhável se outro programa esperasse que o diretório tivesse esse nome específico.

    
por 05.06.2018 / 13:27
7

find executa o comando -exec , ele não envolve um shell. Mesmo se o fizesse, a mudança de diretório só persistiria até que o shell fosse encerrado, imediatamente após o cd .

Você precisará obter o nome do arquivo para o shell atual em cd . Dependendo de quão ruins são os seus nomes de arquivos, você pode usar a substituição de comandos:

cd "$(find . -inum 888696)"

Isso não funcionará se o nome do arquivo terminar em uma nova linha, já que a substituição de comandos come novas linhas. Nesse caso, você precisa proteger a nova linha e se livrar da find adicionada ao imprimir:

dir=$(find . -inum 888696; echo x)
cd "${dir%?x}"

Ou, com GNU find , não imprima a nova linha à direita (mas ainda proteja qualquer no nome do arquivo):

dir=$(find . -inum 888696 -printf "%px" -quit)
cd "${dir%x}"

Também usando o predicado -quit (também uma extensão GNU), para parar de cuidar da primeira correspondência como uma otimização.

Como alternativa, você pode iniciar um novo shell a partir de find , mas é um pouco feio:

find . -inum 888696 -exec bash -c 'cd "$1" && exec bash' sh {} \;
    
por 05.06.2018 / 13:24
5

Não com exec, mas isso pode ser bom o suficiente para você:

cd "$(find . -inum 888696 -type d)"

O "-type d", só para ter certeza. De que eu realmente não sei.

    
por 05.06.2018 / 13:23
4

Use um fluxo delimitado por NUL para ler a saída de find que funciona em todos casos - incluindo nomes que terminam em novas linhas. Além disso, você pode usar printf '%q' para gerar uma representação legível de um nome de arquivo.

inum=888696
if IFS= read -r -d '' filename < <(find . -inum "$inum" -print0); then
  LC_ALL=C printf 'Located filename: %q\n' "$filename" >&2
  cd -- "$filename"
else
  echo "No file located for inode $inum" >&2
fi
    
por 05.06.2018 / 19:26
3

Se você receber essa mensagem, a plataforma do seu SO estará com problemas. O padrão POSIX requer que um comando chamado cd esteja disponível no sistema de arquivos para que possa ser chamado via exec() .

Agora, a má notícia para você:

Mesmo se a sua plataforma de SO não apresentar erros, você simplesmente não visualizou um aviso, mas não obteve os resultados esperados, pois isso não ajuda se um programa separado alterar seu diretório de trabalho atual e morre imediatamente depois disso.

Se você gosta de ter um cd efetivo em um comando executado por find , você pode fazer algo como:

find . -type d -exec sh -c 'cd "$1"; some other command' dummy {} \;
    
por 05.06.2018 / 14:09