A página de manual do GNU encontra estados:
-exec command ; [...] The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell.
Isso é do homem para find
(GNU findutils) 4.4.2.
Agora eu testei isso com bash e dash, e ambos não precisam ter o {}
mascaramento. Aqui está um teste simples:
find /etc -name "hosts" -exec md5sum {} \;
Existe uma concha, para a qual eu realmente preciso mascarar o aparelho? Observe que isso não depende se o arquivo encontrado contém um espaço em branco (chamado a partir do bash):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Isso muda se o arquivo encontrado for passado para um subshell:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \;
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory
que pode ser resolvido por:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
em contraste com:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
mas não é disso que a página de manual está falando, é? Então, qual shell trata {}
de uma maneira diferente?
Respostas:
Resumo : se já houve um shell que se expandiu
{}
, é realmente um legado antigo até agora.No shell Bourne e em shells compatíveis com POSIX, chaves (
{
e}
) são caracteres comuns (diferentes(
e)
que são delimitadores de palavras como;
e&
,[
e]
quais são caracteres brilhantes). As seguintes seqüências de caracteres devem ser impressas literalmente:Uma palavra que consiste em uma única chave é uma palavra reservada , que só é especial se for a primeira palavra de um comando.
O Ksh implementa a expansão de chaves como uma extensão incompatível para o shell Bourne. Isso pode ser desativado com
set +B
. O Bash emula o ksh a esse respeito. O Zsh também implementa expansão de chaves; lá pode ser desligado comset +I
ousetopt ignore_braces
ouemulate sh
. Nenhum desses shells se expande{}
em nenhum caso, mesmo quando é uma substring de uma palavra (por exemplofoo{}bar
), devido ao uso comum nos argumentos parafind
exargs
.O Unix v2 único observa que
Esta nota foi descartada nas versões subsequentes do padrão; os exemplos para
find
ter usos sem aspas de{}
, assim como os exemplos paraxargs
. Pode ter havido{}
citações históricas de Bourne onde precisavam ser citadas, mas agora seriam sistemas legados realmente antigos.As implementações do csh que tenho em mãos (OpenBSD 4.7, BSD csh no Debian , tcsh) se expandem
{foo}
parafoo
apenas deixar em{}
paz.fonte
bash
(veja$BASH_VERSION
). A expansão da cinta está muito viva e bem.{}
sintaxe teve origemcsh
, mas foi{}
expandida para a sequência vazia. Os reservatórios mais recentes reconhecem que isso não faz sentido, mas ainda existem alguns velhoscsh
por aí.{}foo
expandiria parafoo
, mas{}
expandiria para{}
(exceto quando dentro de backticks, mas a citação não ajudaria) e foi documentado como tal. Eu verifiquei para o csh de 2BSD (primeira versão), 2.79BSD, 2.8BSD e 2.11BSD.O
{}
necessário para ser citado nas versões dofish
shell anteriores à 3.0.0.E no shell rc (também
akanga
baseado emrc
, mas nãoes
):Provavelmente, essas não são as conchas que os autores desse GNU acham que a documentação tinha em mente quando escreveram esse texto desde que
fish
foi lançado pela primeira vez em 2005 (enquanto esse texto ou similar já existia em 1994) erc
não era originalmente um shell Unix.Existem alguns rumores de que algumas versões
csh
(o shell que introduziu a expansão de chaves) exigiam isso. Mas é difícil dar crédito àqueles desde o primeiro lançamento docsh
2BSD não. Aqui, como testado em um emulador PDP11:E a página de manual do 2BSD
csh
afirma claramente :Então, eu acharia muito estranho se uma versão subseqüente do csh ou do tcsh quebrasse isso posteriormente.
Poderia ter sido contornar alguns erros em algumas versões. Ainda com esse csh 2BSD (isso é o mesmo em 2.79BSD, 2.8BSD, 2.11BSD):
A citação não ajuda, porém:
Você pode citar toda a substituição do comando:
Mas isso está passando um argumento para esse eco externo.
Em
csh
outcsh
, você precisa citar o{}
quando não está sozinho, como em:(embora esse tipo de
find
uso não seja portátil, pois algunsfind
s se expandem apenas{}
por conta própria).fonte
Em uma palavra
csh
.bash
e outros shells modernos reconhecem que o usuário provavelmente não está solicitando uma expansão de chave nula. (Modernocsh
é realmentetcsh
e também pode lidar com{}
sanidade a essa altura.)fonte
csh
. Nem todo mundo executa utilitários GNU no Linux; de fato, é bastante comum instalá-los em sistemas Unix comerciais mais antigos, cujos comandos agrupados são limitados. (A substituiçãocsh
nesses sistemas é menos provável, porque os scripts do sistema podem depender das idiossincrasias do originalcsh
e, mesmo que todos os usuários tenham sido configurados para usar um mais novocsh
,root
quase certamente precisará permanecer a versão em pacote.)pdksh
faz a coisa certa ... embora a resposta correta para isso seja provavelmente "realksh
é o software livre atualmente"...
para ksh93, bash e zsh). Somente se expande (t) csh{foo}
parafoo
, e até mesmo deixa{}
sozinho (pelo menos no recente BSD 's).