¿Diferencia entre '{}' y {} en el comando find?

18

En la documentación , veo el uso en ambos sentidos:

find . -type f -exec file '{}' \;

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
tarabyte
fuente
44
Claro parece que no tiene nada que ver con el comando find, y en cambio tiene que ver con las comillas apropiadas para el comando que se llama.
Zoredache
1
Pruébalo con pescado, en lugar de golpear.
Charles Duffy el

Respuestas:

24

Para el bashcaparazón, '{}'y {}son intercambiables. Este no es el caso con todos los shells (como fish).

Poner el argumento entre comillas simples indica explícitamente que se deben enviar las llaves find. Dependiendo del uso, el shell bash a veces sustituye el contenido de las llaves.

Como se ve a continuación, bash no sustituye los corchetes vacíos, y se pasan al comando. Para el findcomando, no importa.

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}
Steven
fuente
44
No importa con bash. Importa con el pescado.
Charles Duffy el
1
Reemplazaría " are interchangeable"con " are interchangeable in some shells, not in all of them. ALWAYS use the single quotes to make sure they get passed as-is to the find command"(los buenos hábitos comienzan asegurándome de usar la forma correcta incluso si sucede (¿siempre?) En un sistema que permite el ambiguo)
Olivier Dulac
9

Con casi todos los intérpretes de shell disponibles, no hay absolutamente ninguna diferencia entre '{}'y {}.

Las comillas simples se usan normalmente para proteger la cadena incrustada de ser sustituida por otra cosa, por ejemplo:

  • 'a b' es un parámetro único de tres caracteres, sin las comillas que serían dos parámetros de un solo carácter
  • '$b' es literalmente el signo de dólar seguido de la letra b, sin la comilla que sería lo que contiene la variable b y posiblemente nada si no está establecida
  • '!!' son signos de exclamación literales sin comillas y con algunos shells interactivos, se expandirían hasta el último comando puesto en el historial
  • '*' es un asterisco literal, sin comillas, sería reemplazado por la lista de nombres de archivo no ocultos en el directorio actual.

Ya que ni el estándar POSIX ni la corriente principal de conchas ( sh(Bourne), ksh, bash, ash, dash, zsh, csh, tcsh) ampliar {}a otra cosa, no se requieren las comillas.

Sin embargo, hay un shell exótico, llamado fish, que se expande {}como una cadena vacía, por ejemplo:

> ps -p %self
  PID TTY          TIME CMD
 5247 pts/1    00:00:00 fish
> echo a {} b '{}'
a  b {}

Esa es probablemente la razón por la cual la finddocumentación de GNU sugiere proteger {}contra la interpretación con comillas o barras invertidas.

jlliagre
fuente
9

Para la mayoría de los usuarios (particularmente aquellos que usan shells POSIX), no hay diferencia.

De acuerdo con la sección de ejemplos de la página del manual para GNU find:

Tenga en cuenta que los corchetes están entre comillas simples para protegerlos de la interpretación como puntuación de script de shell.

Creo que el (los) autor (es) de la página de manual de GNU están errando por el lado de la precaución, pero noto que no todos los ejemplos en su página de manual citan los corchetes. Estos ejemplos de la documentación oficial de búsqueda de GNU también omiten la cita.

En los ejemplos de la especificación POSIX / Single UNIX, las llaves no se citan cuando se usan con la -execopción.

Con un shell POSIX, la expansión de parámetros solo ocurre cuando hay parámetros especiales encerrados dentro de las llaves, pero no con llaves vacías .

El shell Bash incluye la expansión de llaves como una característica (no portátil), pero dichos patrones solo se expanden cuando se incluyen una coma o puntos dentro de las llaves . Bash también usa llaves para la agrupación de comandos , pero esto no ocurre a menos que realmente haya un grupo de comandos dentro de la llave.

Por último, he intentado correr find -exec ls -l {} \;en sh, dashy tcshaunque ninguna de estas conchas ampliado el {}en cualquier otra cosa. Como otros han señalado, el fishshell trata {}especialmente, pero este no es un shell POSIX (que sus creadores y usuarios consideran una ventaja). No hace daño citar los aparatos ortopédicos, pero los mecanógrafos perezosos que no usan la concha de pescado no deberían sentirse culpables por omitirlos.

Anthony G - justicia para Monica
fuente
no están errando, están tratando de asegurarse de que la gente use la forma correcta (es decir, use en '{}'lugar de {}) para que su shell envíe {}al comando find sin interpretarlo (como se mencionó anteriormente por @ Charles-Duffy, si utiliza pescado) , interpretará {}pero no '{}', por lo que debe usar este último en ese shell (¡y en varios otros!). Por lo tanto, siempre use '{}'para evitar ser mordido por la ambigüedad de{}
Olivier Dulac
6

Esto depende de la sintaxis de su shell. En caso de duda, ¡repítalo!

Ejecuta esto

echo '{}'

y esto.

echo {}

Si producen la misma salida, entonces la respuesta para su shell es sí. Como otros han señalado, al menos será sí en bash y no en peces. El resultado es para lo que debe consultar la página de manual de un comando dado.


Si desea ser útil, incluso puede prefijar echouna línea de comando completa para ver el comando real , con todos sus argumentos, que su shell realmente invocaría. Sin embargo, tenga en cuenta que la lista que comprende el comando más los argumentos es una verdadera matriz de cadenas, cada una posiblemente vacía o con espacios en blanco, pero echo la imprime ambiguamente como una lista separada por espacios.

Como se puede verificar con este comando echo un poco más detallado (que muestra argumentos entre comillas guillemet),

#!/bin/sh
for a in "$@"; do
    printf '«%s» ' "$a"
done
echo ''

escribiendo esto en la línea de comando,

find 'My Documents and Settings' -type f -exec file {} \;

significa esto para golpear:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»

y esto en pescado:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»

Como consejo general, nunca está de más citar.

usuario2394284
fuente