¿Hay alguna manera de combinar lógicamente dos comandos de shell que se invocan con find - exec ?
Por ejemplo, para imprimir todos los archivos .csv que contienen la cadena foo junto con su aparición, me gustaría hacer:
find . -iname \*.csv -exec grep foo {} && echo {} \;
pero bash se queja con "argumento perdido para '-exec'"
-exec
en secuencia o usar uno solo-exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;
.sh
(en este caso{}
) sea$1
y$0
sea algo asísh
. Pero, de hecho, tienes razón, el primer argumento aparece como$0
. Tener el primer argumento como el nombre del comando de invocación es solo una convención, que no se aplica automáticamente en estos casos.Respuestas:
-exec
es un predicado que ejecuta un comando (no un shell) y se evalúa como verdadero o falso en función del resultado del comando (estado de salida cero o no cero).Asi que:
sería imprimir la ruta del archivo, si
grep
los hallazgos de Foo en el archivo. En lugar de-print
que pueda usar otro-exec
predicado o cualquier otro predicadoVea también los operadores
!
y-o
find para negación y or .Alternativamente, puede iniciar un shell como:
O para evitar tener que iniciar un shell para cada archivo:
fuente
El problema que enfrenta es que el shell primero analiza la línea de comando y ve dos comandos simples separados por el
&&
operador:find . -iname \*.csv -exec grep foo {}
yecho {} \;
. Citando&&
(find . -iname \*.csv -exec grep foo {} '&&' echo {} \;
) no pasa por eso, pero ahora el comando ejecutado porfind
algo así comogrep
con los argumentosfoo
,wibble.csv
,&&
,echo
ywibble.csv
. Debe indicarlefind
que ejecute un shell que interpretará al&&
operador:Tenga en cuenta que el primer argumento después
sh -c SOMECOMMAND
es$0
, no$1
.Puede guardar el tiempo de inicio de un proceso de shell para cada archivo agrupando las invocaciones de comando con
-exec … +
. Para facilitar el procesamiento, pase un valor ficticio$0
para"$@"
enumerar los nombres de archivo.Si el comando de shell solo tiene dos programas separados
&&
,find
puede hacer el trabajo por sí mismo: escriba dos-exec
acciones consecutivas , y la segunda solo se ejecutará si la primera sale con el estado 0.(Supongo que
grep
yecho
son solo para fines ilustrativos, ya que-exec echo
pueden reemplazarse-print
y el resultado resultante no es particularmente útil de todos modos).fuente
./some-file: grep: command not found
mensaje de error confuso .-exec find sh -c '... "$1"' sh {} \;
No tendría el problema. Hay un error tipográfico (relacionado) en su segundo comando de búsqueda.En este caso específico, haría:
find . -iname \*.csv -exec grep -l foo \{\} \;
O si tienes ack :
ack -al -G '.*\.csv' foo
Para responder a su pregunta real, algo como esto puede funcionar:
find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;
fuente