Substituição de comandos - aspas simples e espaços

2

Como posso fazer a substituição de comandos passar uma lista de caminhos POSIX com aspas simples separados por espaços?

command1 $(command2)
command1 '/path/to/file 1' '/path/to/file 2' '/path/to/file 3'

Como posso rastrear a expansão?

    
por 1.61803 16.04.2013 / 14:43

5 respostas

2

Você pode ver exatamente qual comando está sendo executado usando set -x . Um exemplo bastante bobo:

$ echo $(echo "foo 'bar baz' taz\ jaz")
foo 'bar baz' taz\ jaz

vai dar:

++ echo 'foo '\''bar baz'\'' taz\ jaz'
+ echo foo ''\''bar' 'baz'\''' 'taz\' jaz
foo 'bar baz' taz\ jaz

Isto é um pouco difícil de ler, por causa de todo o escape. Por exemplo, essa segunda palavra:

  1. '' não é nada.
  2. \' se torna uma cotação única ( ' )
  3. 'bar' se torna bar

para que o parâmetro seja passado como 'bar . Você pode confirmar com algo assim (supondo que você tenha Data :: Dump instalado, que não é o padrão, infelizmente) Observe que o $(echo… foi copiado na linha perl:

$ perl -MData::Dump=pp -E 'pp @ARGV' $(echo "foo 'bar baz' taz\ jaz")
("foo", "'bar", "baz'", "taz\", "jaz")

O que está acontecendo aqui é que o bash está fazendo a divisão de palavras (com base em $IFS ) e não a análise de argumentos. Então, infelizmente, você provavelmente terá que usar eval e lidar com todo o risco que isso implica.

$ eval "echo $(echo "foo 'bar baz' taz\ jaz")"
foo bar baz taz jaz

(Além disso, observarei, se você conseguir que seu comando gere sua saída como uma lista de nomes, separados por NUL, isso seria fácil para lidar com xargs -0 e mais, totalmente seguro).

    
por 16.04.2013 / 18:54
0

Tente algo assim: -

path1="/etc/passwd"
path2="/var/log/secure"

[root@localhost base_filters]# ls -l "$path1" "$path2"
-rw-r--r--. 1 root root 1876 Mar 10 22:15 /etc/passwd
-rw-------. 1 root root 2408 Apr  5 23:09 /var/log/secure
    
por 16.04.2013 / 14:49
0

Não sei se entendi completamente sua pergunta, mas isso ajudará:

$ var=$(echo "'/path/to/dir 1' '/path/to/dir 2' '/path/to/dir 3'")
$ echo -n $var | sed "s/^'\(.*\)'\$//g" | sed "s/' '/\x00/g" | xargs -0 command1
    
por 16.04.2013 / 19:13
0

Tente brincar com a variável IFS, para que o espaço não afete o seu script. Eu armazenaria o IFS em uma variável e depois de concluir as ações do meu script, restauraria o IFS.

    
por 16.04.2013 / 21:51
0

Você está na posição rara de ter uma lista de arquivos que estejam em um formato que xargs entenda. Então corra

command1 | xargs command2

Observe que, em algumas variantes unix, se a saída de command1 for enorme, será impossível executar command2 com todos os nomes de arquivos devido ao limite de comprimento da linha de comando. A desvantagem de usar xargs é que ele executará o comando várias vezes em vez de relatar corretamente um erro. Você pode verificar o limite de comprimento da linha de comando com getconf ARG_MAX .

    
por 17.04.2013 / 01:49