CD. tem uso?

102

Um dos tutoriais que acompanho afirmou brevemente que cd .não tem utilidade. Ao tentar replicar o problema mostrado pelo OP na recursão do link simbólico - o que o faz "redefinir"? , Também tentei cd ., que mostrou o mesmo efeito descrito no OP ( $PWDvariável crescente ), que pode ser combatido cd -P.

Isso me faz pensar: existe algum caso em que alguém realmente queira usar cd . ?

Sergiy Kolodyazhnyy
fonte
20
Eu tenho um .zshrc personalizado que executa várias verificações no diretório ao mudar de diretório, por exemplo, uma das opções é ativar / desativar automaticamente um virtualenv correspondente ao mover diretórios. Ocasionalmente, posso iniciar um novo shell ou o que quer que seja, e essas verificações não são executadas, e geralmente uso cd .para acioná-las porque é curta e simples. Embora eu pense que você pretendeu que a pergunta fosse para um ambiente de baunilha.
Lie Ryan
29
Além do efeito (óbvio) $PWD, cd .também muda $OLDPWDpara o diretório atual. (Atualmente) não tenho idéia do por que isso pode ser útil, mas por uma questão de perfeição ...
Andreas Wiese
5
Acho que nunca precisei cd ., embora, ao ver as respostas abaixo, possa no futuro, mas às vezes usei pushd .quando queria popdvoltar a esse diretório mais tarde. por exemplo, ao executar um script de compilação configure, cd output...e make, e quando estiver pronto, vou querer voltar ao diretório original. Em vez de manter minha própria cópia do buildscript que é diferente do que todo mundo espera, eu apenas o executo pushd .; ./BuildScriptName.sh; popd, e isso também me dá a liberdade de não popdalgumas vezes, e depois popdmais tarde.
3D1T0R 23/01
5
Sem mencionar, é claro, que '.' e '..' não são implementados no próprio comando cd; portanto, ninguém se propôs a criar esse recurso específico, é apenas uma combinação de coisas que não servem a nenhum propósito real.
David S
1
@ruakh Não, programas externos não devem afetar o ambiente de execução do shell. É principalmente para a conformidade do POSIX, que requer que alguns utilitários existam fora do shell e para avaliar o status de saída de comandos externos. Você pode ler sobre o objetivo /bin/cdaqui unix.stackexchange.com/q/50058/85039
Sergiy Kolodyazhnyy 25/01

Respostas:

158

Eu acho que isso está exagerando no problema. cd .pode não ser algo que seria executado manualmente no curso normal, mas definitivamente é algo que pode surgir na execução programática (pense em qualquer situação em que você possa encontrar cdo diretório que contém um arquivo, cujo caminho é fornecido pelo usuário ) Portanto, ele não precisa ter um uso específico: desde que cumpra a semântica usual cd <some-path>, é útil.

Olorin
fonte
12
Concordado, .deve ser tratado como um caminho válido especificado pela cdsintaxe.
Sergiy Kolodyazhnyy 22/01
18
Você pode adicionar o seguinte exemplo: Loops like while IFS= read Dir; do cd "$Dir"; do_something; done < <(find . -type d). Durante seu curso, find produz .como caminho, para que o comando se cd "$Dir"expanda para cd .. Portanto, nos scripts, é perfeitamente útil.
rexkogitans 22/01
5
Por exemplo, um script realmente é executado cd ${path_to_directory}, mas em algum momento o diretório é o diretório atual e, path_to_directory = .portanto, você precisa cd .trabalhar apenas por precaução.
Demis
4
Em outras palavras, sua utilidade é o fato de tornar desnecessário o código extra ( ifverificações e elsecláusulas, qualquer tipo de revestimento especial).
jpmc26 24/01
2
Portanto, é útil no sentido de que x + 0 ou x * 1 são úteis - a operação específica não é útil em si, mas significa que você pode manipular 0 e 1 da mesma forma que qualquer outro valor, sem precisar tratá-los como um caso especial.
user32929 27/01
127

O caminho do diretório poderia ter sido alterado desde que o último comando foi executado, e sem cd .os shells bash e ksh93, o diretório de trabalho lógico descrito no post vinculado na pergunta será chamado, portanto, chamar o cd .que faz com que o shell emita o getcwd()syscall garantirá que seu o caminho atual ainda é válido.

Etapas para reproduzir no bash:

  1. Em uma edição da guia terminal mkdir ./dir_no_1; cd ./dir_no_1
  2. Em uma questão diferente da guia do terminal mv dir_no_1 dir_no_2
  3. Na primeira edição da guia do terminal echo $PWDe pwd. Observe que o diretório foi renomeado externamente; o ambiente do shell não foi atualizado.
  4. Issue cd .; pwd; echo $PWD. Observe que o valor foi atualizado.

O ksh93, no entanto, não atualiza as informações do ambiente; portanto, cd .no ksh93 pode ser realmente inútil. No /bin/dashUbuntu e em outros sistemas baseados no Debian, cd .retorna dash: 3: cd: can't cd to .erro, no entanto cd -P .funciona (ao contrário do ksh93).

Sergiy Kolodyazhnyy
fonte
22
É bom saber: acrescentarei isso à minha lista de informações inúteis. ^^)
jayooin 22/01
12
@jayooin Fico feliz em poder contribuir com a lista;)
Sergiy Kolodyazhnyy
8
Eu acho que você pode fazer mv ../dir_no_1 ../dir_no_2no mesmo terminal / bash.
ctrl-alt-delor 22/01
3
@ ctrl-alt-delor Confirmado, funciona :)
Sergiy Kolodyazhnyy 22/01
1
@ymbirtt Na maioria dos shells, pwdna verdade , é incorporado, no entanto, invocar /bin/pwdnão afeta o ambiente do shell - utilitários externos em geral não afetam o ambiente do shell. A razão pela qual /bin/cde /bin/pwdexiste é para conformidade com POSIX, entre outras coisas. Há uma boa discussão sobre cd externo alguns dos quais provavelmente se aplica a /bin/pwdbem
Sergiy Kolodyazhnyy
55

Outro caso de uso cd .seria quando o diretório em que você está atualmente foi excluído e criado novamente. Considere tentar o seguinte -

  1. Crie um diretório temp
  2. cd temp e então faça um ls
  3. Abra outro terminal, exclua e recrie esse diretório temp
  4. De volta do primeiro terminal, tente fazer um ls. Isso resultaria em um erro -ls: cannot open directory .: Stale file handle
  5. cd . e depois fazer um ls funciona bem
Sahil Agarwal
fonte
3
Isso nem sempre funciona. No traço, por exemplo, você vai ter: cd: can't cd to .Agora que eu olhar para ele, isso já está mencionado na resposta do Sergiy (mover, excluir / recriar - essencialmente o mesmo: o diretório que você está em não é mais o que era no original caminho)
Olorin 22/01
12
Eu uso muito isso testando implantações remotas. O diretório em que estou será excluído e recriado por alguma automação e precisarei emitir cd .para mover para o novo diretório com o mesmo nome.
HP Williams
2
Eu uso cd .o tempo todo quando tenho um shell cujo diretório de trabalho atual foi montado com sshfs, mas a sessão ssh foi fechada e reaberta.
jamesdlin 22/01
4
Nesse caso, eu faço "cd $ PWD". Outras variantes podem funcionar, mas esta expressa claramente a intenção: extrair o que deveria ser o meu caminho atual (isto é, ler o conteúdo da PWDvariável de ambiente) e, em seguida, percorrer a hierarquia do sistema de arquivos da raiz, até um diretório que pode ser acessado via esse caminho, se é realmente o mesmo diretório ou não. Isso se encaixa exatamente no caso de uso nesta resposta.
Stéphane Gourichon 23/01
3
Estou realmente surpreso, chocado, que cd .funciona quando o diretório foi desvinculado e um novo diretório diferente é criado no mesmo caminho do sistema de arquivos. O diretório de trabalho atual foi desvinculado e, presumivelmente, como parte dele, ele não possui mais uma entrada .ou .., e mesmo se tiver, a .entrada deve continuar apontando para si mesma. Parece que o shell ou o kernel está executando o comando cd com base no nome do caminho do diretório, em vez de simplesmente acessar a .entrada. Alguém pode confirmar esse comportamento?
Adrian Pronk
36

Você pode limpar $OLDPWDrapidamente cd ., se houver um caso em que não queira que aponte para qualquer lugar "interessante". Isso também afetará cd -.

unperson325680
fonte
16

Programaticamente, é útil como não operacional. Considere um caminho fornecido a partir da entrada externa.

read -p "Path to file: " p
dirn=$(dirname "$p")
file=$(basename "$p")
echo "dirn=$dirn, file=$file"
cd "$dirn"
ls -ld "$file"

Com um caminho como "fred.txt", o diretório se tornará ., levando acd .

roaima
fonte
1
É útil que ele não gere um erro se você já estiver no diretório para o qual está navegando, mas eu não diria que é útil como não operacional.
Capitão Homem
2
O @CaptainMan não está lançando um erro se você já está no diretório (efetivamente) não é operado. O dirnamecomando gera, .quando necessário, para evitar a quebra de código que espera poder dividir um caminho.
roaima 22/01
15

Isso é comum se você tiver que trabalhar com um cabo USB ruim. Depois que um dispositivo é desconectado e conectado novamente, e montado automaticamente no mesmo diretório, você precisa usá cd .-lo para fazê-lo funcionar novamente.

user23013
fonte
1
Isso não dependerá de que tipo de dispositivo, como ele está sendo acessado, seu sistema de arquivos, sistema operacional, etc.
gidds 24/01
OS, talvez. É improvável que o sistema de arquivos seja relevante, desde que o kernel consiga desmontá-lo enquanto estiver sendo usado. De qualquer forma, o comando tem seu uso na situação exatamente correta.
user23013 24/01
11

Observe que "." é a maneira correta de especificar o nome do arquivo que está aberto como o diretório de trabalho atual de qualquer processo (incluindo um processo de shell, é claro) e "." sempre é um nome válido de um arquivo em todo e qualquer diretório, incluindo o diretório de trabalho atual. O nome .pode não ser um nome válido para um arquivo para uma determinada instância de um processo se, por exemplo, o diretório de trabalho atual subjacente tiver sido removido (ou ficar "ruim", por exemplo, um identificador NFS antigo), mas for um nome válido de um arquivo que é garantido que existe em todos os diretórios válidos.

Portanto, . deve ser um argumento válido para qualquer comando que aceite o nome de um diretório e, portanto, no shell padrão cd .deve ser um comando válido.

Se cd .é útil ou não, depende da implementação do shell. Como mencionado, pode ser útil se o shell redefinir sua idéia interna do nome do caminho completo do diretório de trabalho atual após chamar a chdirchamada de sistema subjacente , por exemplo, se o diretório subjacente (ou algum pai dele) foi renomeado.

Pelo menos alguns shells que eu conheço ( /bin/shno FreeBSD e NetBSD) serão convertidos cd ""em cd ., o que pode ser descrito como um recurso para dar suporte ao uso programático em um shell script em que uma variável pode ser usada como parâmetro (por exemplo, converter uma substituição de variável vazia em um " não faça nada "), embora o histórico de consolidação do FreeBSD diga que a mudança ocorreu diretamente devido à adição do suporte ao POSIX para evitar uma falha chdir(""), da qual os mandatos do POSIX devem falhar.

Alguns outros shells substituirão o que .quer que tenham armazenado como o nome completo do caminho para o diretório de trabalho atual e, portanto, para eles, isso poderá permitir o comportamento mencionado na resposta de Sahil Agarwal .

Greg A. Woods
fonte
4

Eu usei esse comando hoje mesmo quando refiz a nova ramificação em que estava trabalhando no Git, a partir de um diretório que foi criado pela primeira vez na mesma ramificação. O rebase correu bem, mas depois git statusgerou um erro. Depois que cd .tudo estava normal.

(Eu estava trabalhando no MobaXterm no Windows, aliás. Caso você esteja tentando reproduzir isso. Isso pode não acontecer em outros sistemas.)


Também usei esse comando em diretórios que são atualizados por um processo automatizado que se afasta do diretório antigo e o substitui por um novo (por isso é o mais próximo possível do atômico). Não é uma situação comum, mas cd .é exatamente o que é necessário.


Depois de ler esta excelente resposta de Stephane Chazelas:

Agora entendo que meus casos de uso acima funcionam apenas porque estou usando bash, no qual cd .é equivalente a cd "$PWD". Eu recomendo ler a resposta vinculada.

Curinga
fonte
1

Eu uso cd .para executar novamente as coisas que eu sobrecarreguei cdatravés de uma bashfunção.

Do meu ~/.bashrc:

# from the "xttitle(1)" man page - put info in window title
update_title()
{
    [[ $TERM = xterm ]] || [[ $TERM = xterm-color ]]  && xttitle "[$$] ${USER}@${HOSTNAME}:$PWD"
}

cd()
{
    [[ -z "$*" ]] && builtin cd $HOME
    [[ -n "$*" ]] && builtin cd "$*"
    update_title
}
waltinator
fonte
0

EDIT: Isso já foi sugerido por Sahil anteriormente.

Isso é útil se você estiver dentro de uma pasta que foi excluída e recriada por outro processo. Por exemplo, assumindo as duas sessões do terminal $1e $2:

$1 mkdir d
$1 cd d
$1 touch f

$2 rm -rf /path/to/d # delete the folder where $1 is in ...
$2 mkdir /path/to/d # ... and recreate it

$1 touch g # cannot create file g because current dir doesn't exist anymore
touch: cannot touch ‘g’: Stale file handle
$1 cd . # go to the newly created dir (same path)
$1 touch g # works fine now

Não sei se exatamente onde (SO, SHELL, ...?) Está a causa raiz desse comportamento.

Rolf
fonte
Isso já foi mencionado por outras respostas.
Kusalananda
-8

Não, não tem sentido. Nem no script, ele simplesmente não faz nada.

Federico
fonte
2
Dependendo do shell, ele seria redefinido $PWDe possivelmente chamaria outras funções do shell se o usuário fornecesse sua própria cdfunção ou alias para sobrecarregar o interno cd. Ele também verificaria se o diretório atual ainda é válido e se o uso atual tem permissão para estar lá.
Kusalananda
1) é claro que não estamos falando de possíveis aliases personalizados de "cd", mas da compilação padrão 2) como o uso atual pode estar lá se não tiver permissão? Para simplificar, basta dizer que, no mundo real, não há razão para usá-lo na minha opinião.
Federico
1
1) não somos? 2) O mundo real não é simples e o Unix é um sistema operacional multiusuário. Um usuário pode alterar as permissões nos diretórios e, se o script ou o shell interativo de outro usuário tiver esse diretório (ou um subdiretório) como seu diretório de trabalho, cd .reclamará.
Kusalananda
4
Federico, de acordo com as regras do site e minhas próprias regras pessoais, devo rebater a sua resposta. No entanto, você é novo. Bem vinda! Revise algumas das outras respostas . Depois disso, se você acha que sua resposta está errada, exclua-a. Por favor, aproveite para dar outras respostas a esta e outras perguntas.
daveloyall 23/01
2
Especialmente em scripts, às vezes "não faz nada" é exatamente o que é necessário.
Matthew Najmon 27/01