conchas @grawity Unix. Desculpe, eu não mencionei isso.
faressoft
Para o Unix, as respostas abaixo estão corretas. (No Windows, isso é feito por programas individuais - embora geralmente automaticamente pela biblioteca de tempo de execução antes de main ().)
user1686
Respostas:
24
bash (ou o que você usar como shell), é a primeira coisa a ler qualquer entrada e começará a interpretar caracteres especiais como ?e *. *é expandido para quaisquer correspondências no CWD , o que significa que o asterisco é substituído pelas referidas correspondências.
Na maioria dos casos, isso é bastante complicado, mas pode levar a alguns casos confusos de tempos em tempos.
Considere o seguinte. Um diretório possui este conteúdo:
teste (arquivo regular)
test1 (diretório)
test2 (diretório)
test3 (diretório)
Se você digitar mv *algo aparentemente estranho, acontece: test3existe, mas o resto se foi. Embora estranho no começo, faz sentido quando você entende o que o bash realmente passa mv. Por causa do asterisco, o bash interpreta mv *como mv test test1 test2 test3e, quando mv obtém essa lista, assume-se que o último argumento é o destino, que é onde todos os arquivos teriam sido movidos.
Quanto aos comandos que você listou:
echo *pode funcionar como um homem pobre ls. O shell expandirá o asterisco para o que estiver nesse diretório e, como tenho certeza de que você já sabe, echoliteralmente ecoará qualquer coisa que o bash passar a ele como argumentos.
cp temp temp*terá um comportamento semelhante ao mvcomando que descrevi acima, a menos que haja apenas um diretório chamado temp; nesse caso, o nome de origem e destino é o mesmo, ou seja, não fará nada.
Não há nada de "ruim" em usar em *vez de ls. Por exemplo, for f in *; doé mais confiável do que for f in $(ls)se um nome de arquivo contiver espaço em branco ou caractere glob. (Será, no entanto, falhar se não houver arquivos na CWD, então você precisa verificar para esse caso.)
Fazendo o chiming com: arquivos anexados com "-" em pastas arbitrárias que acionam opções indesejáveis. Removê-los não é muito divertido até você perceber que o arquivo rm ./-stupid funciona.
ǝɲǝɲbρɯͽ
11
@ ǝɲǝɲbρɯͽ Notei quando certa vez precisei excluir o conteúdo de um diretório que continha arquivos com o nome do arquivo representando posições em um sistema de coordenadas, de -1024x-1024 a 1024x1024. Foi quando eu aprendi sobre como fugir.
Jarmund #
5
Como já foi dito, o shell se expande *para echoreceber como argumentos o que o shell encontrar no diretório atual. No entanto, observe que, se a expansão não resultar em nada, ou seja, nesse caso, se o diretório não contiver arquivos não ocultos, ele *permanecerá inalterado e transmitido como está para o comando chamado (a menos que opções não padrão sejam usadas com alguns shells como bash). echo *não vai se comportar como um homem pobre, lspois o primeiro não imprime nada enquanto o segundo imprime *.
Da mesma forma, cp /tmp/temp temp*criará um arquivo nomeado temp*no diretório atual se ainda não houver pelo menos um arquivo com o qual o nome comece temp.
Por fim, se você deseja que a *transmissão seja inalterada, seja qual for o caso, é possível protegê-lo da expansão usando aspas simples '*', aspas duplas "*"ou barra invertida \*.
No Bash, o shell lida com isso. Você vê que, se você tentar *sem eco
Nota: com base em alguns comentários, sugiro que, ao executar * ENTER, crie um diretório e use o comando touch para criar alguns arquivos e verifique se nenhum deles, ou pelo menos verifique se o primeiro em ordem alfabética não é o nome de qualquer script ou comando no caminho.
$ *
bash: a: command not found
$ echo *
a a.aa a.ab a.b a.htm a.tx
Então ls *é um pouco de clichê
No Windows, *é tratado pelo comando, portanto, dir *.*não é um clichê.
Nota- Vendo alguns comentários, eu acrescentaria, há um risco correndo * e depois ENTER. Se você tem um arquivo chamado rm, o primeiro na lista de diretórios, é perigoso porque qualquer coisa após a exclusão será excluída. Além disso, e isso é menos improvável, se o primeiro arquivo na lista de diretórios for o nome de um script no caminho, ele será executado.
Observe que pode haver um arquivo chamado rm, é claro.
Volker Siegel
11
... e um outro chamado rf
ǝɲǝɲbρɯͽ
11
@ ǝɲǝɲbρɯͽ você pode ter um arquivo cujo nome de arquivo é -rf? Eu tentei touch -rfe touch \-rfmas não está criando.
barlop
@ Barlop comentei acima; o gui (como o gedit) lida com eles muito bem, mas como o shell (pelo menos o bash) passa isso por ele requer ./ na frente. Se você criar um arquivo acidentalmente, o rm tenta sugerir, mas se não o fizer: espero que isso acabe em uma pasta temporária com filhos descartáveis.
ǝɲǝɲbρɯͽ
@ ǝɲǝɲbρɯͽ Eu não entendo o que quer dizer em tudo, eu estou perguntando como você pode criar um arquivo que é chamado -rf? (Eu entendo o perigo de um arquivo chamado rm e um arquivo chamado -rf, eo problema de digitação * e empurrando entrar em uma pasta importante, eu não planejo fazer isso)
barlop
-1
O shell executa várias expansões antes que os argumentos sejam entregues ao comando.
Tecnicamente, o que você está escrevendo está correto, mas sem os links, essa resposta realmente não faz nada para responder à pergunta. Considere incorporar os detalhes relevantes.
um CVn
@ MichaelKjörling Eu concordo com o assunto sobre os links, mas o OP simplesmente perguntou se o shell ou o próprio comando lidava com os argumentos. A resposta de Glenn simplesmente afirma que o shell lida com eles, portanto é uma resposta aceitável para a pergunta.
slhck
@slhck É por isso que não sinalizei como NAA: ainda resta algo que aborda a questão depois de remover os links. Isso não significa que esta seja uma boa resposta para mim . (Agora vejo que o meu comentário inicial poderia ser interpretado de outra forma, por isso, peço desculpas, mas eu ainda acho que tem valor suficiente para deixá-lo onde está.)
um CVn
@ MichaelKjörling concordou. Acabei de deixar o comentário para quem fez (e vai) sinalizar como NAA.
Respostas:
bash (ou o que você usar como shell), é a primeira coisa a ler qualquer entrada e começará a interpretar caracteres especiais como
?
e*
.*
é expandido para quaisquer correspondências no CWD , o que significa que o asterisco é substituído pelas referidas correspondências.Na maioria dos casos, isso é bastante complicado, mas pode levar a alguns casos confusos de tempos em tempos.
Considere o seguinte. Um diretório possui este conteúdo:
Se você digitar
mv *
algo aparentemente estranho, acontece:test3
existe, mas o resto se foi. Embora estranho no começo, faz sentido quando você entende o que o bash realmente passamv
. Por causa do asterisco, o bash interpretamv *
comomv test test1 test2 test3
e, quando mv obtém essa lista, assume-se que o último argumento é o destino, que é onde todos os arquivos teriam sido movidos.Quanto aos comandos que você listou:
echo *
pode funcionar como um homem pobrels
. O shell expandirá o asterisco para o que estiver nesse diretório e, como tenho certeza de que você já sabe,echo
literalmente ecoará qualquer coisa que o bash passar a ele como argumentos.cp temp temp*
terá um comportamento semelhante aomv
comando que descrevi acima, a menos que haja apenas um diretório chamado temp; nesse caso, o nome de origem e destino é o mesmo, ou seja, não fará nada.fonte
*
vez dels
. Por exemplo,for f in *; do
é mais confiável do quefor f in $(ls)
se um nome de arquivo contiver espaço em branco ou caractere glob. (Será, no entanto, falhar se não houver arquivos na CWD, então você precisa verificar para esse caso.)shopt nullglob
serve.echo *
, esse truque pode salvar você em alguns casos.Como já foi dito, o shell se expande
*
paraecho
receber como argumentos o que o shell encontrar no diretório atual. No entanto, observe que, se a expansão não resultar em nada, ou seja, nesse caso, se o diretório não contiver arquivos não ocultos, ele*
permanecerá inalterado e transmitido como está para o comando chamado (a menos que opções não padrão sejam usadas com alguns shells comobash
).echo *
não vai se comportar como um homem pobre,ls
pois o primeiro não imprime nada enquanto o segundo imprime*
.Da mesma forma,
cp /tmp/temp temp*
criará um arquivo nomeadotemp*
no diretório atual se ainda não houver pelo menos um arquivo com o qual o nome comecetemp
.Por fim, se você deseja que a
*
transmissão seja inalterada, seja qual for o caso, é possível protegê-lo da expansão usando aspas simples'*'
, aspas duplas"*"
ou barra invertida\*
.fonte
No Bash, o shell lida com isso. Você vê que, se você tentar
*
sem ecoNota: com base em alguns comentários, sugiro que, ao executar * ENTER, crie um diretório e use o comando touch para criar alguns arquivos e verifique se nenhum deles, ou pelo menos verifique se o primeiro em ordem alfabética não é o nome de qualquer script ou comando no caminho.
Então
ls *
é um pouco de clichêNo Windows,
*
é tratado pelo comando, portanto,dir *.*
não é um clichê.Nota- Vendo alguns comentários, eu acrescentaria, há um risco correndo * e depois ENTER. Se você tem um arquivo chamado rm, o primeiro na lista de diretórios, é perigoso porque qualquer coisa após a exclusão será excluída. Além disso, e isso é menos improvável, se o primeiro arquivo na lista de diretórios for o nome de um script no caminho, ele será executado.
fonte
rm
, é claro.-rf
? Eu tenteitouch -rf
etouch \-rf
mas não está criando.-rf
? (Eu entendo o perigo de um arquivo chamado rm e um arquivo chamado -rf, eo problema de digitação * e empurrando entrar em uma pasta importante, eu não planejo fazer isso)O shell executa várias expansões antes que os argumentos sejam entregues ao comando.
Veja também https://www.gnu.org/software/bash/manual/bashref.html#Simple-Command-Expansion
Não é específico do bash, consulte http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01
fonte