Como citar uma string contendo cifrão $ e aspas simples '?

6

O nome do meu diretório contém $ e ' , por exemplo

:~$ export DIR=\$my\'dir
:~$ sh -c "ls $DIR"

Como posso executar o comando acima sem o $my ser expandido? Eu sei que a aspa simples não funciona, pois o $DIR contém uma.

Desculpe se a minha pergunta acima não está clara. Na verdade, a questão surgiu do uso do comando find da seguinte forma:

:~$ find ./\$my\'dir -type d -exec sh -c 'ls "{}"' \;

Ele diz ./\'dir: No such file or directory , se eu remover as aspas duplas, ele diz unexpected EOF while looking for matching ' .

    
por will hunt 26.02.2014 / 05:56

4 respostas

4

Uau, algumas soluções complexas aqui! Acho que tudo o que você precisa fazer é isto:

find ./\$my\'dir -type d -exec sh -c 'ls "$1"' sh {} \;

Em vez de colocar os argumentos na sequência de comandos sh , use-os como argumentos para sh . Observe que o segundo sh é o valor de $0 , tudo depois disso é um argumento posicional.

Quanto ao seu problema completo de encontrar diretórios que não contenham PDFs, você sempre estará melhor usando find para esse tipo de coisa, em vez de ls . Isso deve estar perto do que você está procurando:

find . -type d \
  -exec sh -c '[ "$(find "$1" -maxdepth 1 -type f -iname "*.pdf")" = "" ]' sh {} \; \
  -print
    
por 26.02.2014 / 13:19
3

Ok ... aqui está uma maneira complicada de fazer isso. Ele falhará se os nomes dos arquivos contiverem novos caracteres de linha.

  find . -type d -print0                          \ # get the directory list,
                                                  \ # separated by nulls
| xargs -0 ls -1 -d -Q --quoting-style=shell      \ # pick it with xargs, and use
                                                  \ # ls to apply shell quotes to each
                                                  \ # entry
| xargs -d '\n' -I '{}'                           \
        sh -c "ls {} | grep -qi \.pdf$ || echo {}"  # pick each quoted entry
                                                    # with xargs again
                                                    # (using -d, so it keeps the quotes)
                                                    # and insert it in the string

Isso depende de ls -Q --quoting-style=shell citando aspas simples ... caso contrário, use aspas simples no argumento para sh -c .

Ugh.

    
por 26.02.2014 / 12:44
1

O que você deseja não é facilmente possível porque não é possível citar somente strings arbitrárias de "fora" (ou seja, colocando em "" ou '' ). Isso pode ser feito citando cada caractere com \ , mas não vejo como isso deve ser feito simultaneamente ao chamar o shell.

Isso é possível:

echo "$DIR" | sed -e 's/./\&/g' -e 's/^.*$/echo &/' | bash -s

Mas isso não pode ser colocado em uma instrução -exec . E o echo não pode ser chamado de um shell porque esse shell teria o problema de aspas com o argumento. Você pode fazer com que o find imprima a entrada do shell:

find ./\$my\'dir -type d -print0  | xargs -0 -n 1 ls

Mas: Você poderia escrever a string em um arquivo e fazer o shell ler a partir daí:

find ./\$my\'dir -maxdepth 0 -type d -fprint tmpfile -exec bash -c 'cat tmpfile' \;

Desculpe, não, nem isso funciona: find abre o arquivo, a -exec action e depois escreve no arquivo ... Então ... isso funciona, mas é gentil de louco, claro:

find ./\$my\'dir -maxdepth 0 -type d -fprint tmpfile -exec bash -c '(sleep 1; cat tmpfile)&' \;
    
por 26.02.2014 / 06:16
0

Não sei se entendi o seu problema:

$ mkdir \$my\'dir
$ touch \$my\'dir/foo
$ ls $DIR
foo

Quanto à localização de subdiretórios que não incluem arquivos PDF, basta executar isso:

find . -type d -print0 | while IFS= read -r -d '' dir; do 
    [ $(find "$dir" -iname "*.pdf"  | wc -l) -gt 0 ] || echo $dir; 
done
    
por 26.02.2014 / 17:02