Tengo dificultades para escapar y evaluar la expresión. Estoy intentando ejecutar un comando dentro de una find
... -exec COMMAND
estructura, donde COMMAND
opera en un archivo y genera salida a la salida estándar. Para usar esto COMMAND
normalmente en la línea de comando, simplemente redirijo a un archivo nuevo, como este:
COMMAND inputfilename.md > outputfilename.md.conf
Esto funciona bien. Sin embargo, si quiero recorrer recursivamenteTODOlos archivos en un directorio y su subdirectorio, usando find -exec
, parece que no puedo entender cómo separar el nombre del archivo y la ruta para poder redirigir correctamente. Por ejemplo, esto produce un error:
find ./ *.md -not -path './/.git/*' -exec COMMAND '{} > ~/wiki/newdirectory/{}.cong' \;
porque {}
expande toda la ruta del archivo. Probé varias combinaciones de basename
y dirname
, pero parece que no puedo lograr que se evalúen (en cambio, solo obtengo la cadena 'nombre base', etc.). Por ejemplo, esto no funcionó porque el texto 'nombre base' simplemente aparece
find ./ *.md -not -path './/.git/*' -exec COMMAND '{} > ~/wiki/newdirectory/''basename {}''.conf' \;
(devuelve este error 'No such file or directory - .//newdirectory/README.md.conf > ~/wiki/newdirectory/basename .//newdirectory/README.md.conf'
:).
Cualquier ayuda sería apreciada. En resumen, el objetivo es:
- Iterar recursivamente sobre todos los archivos que coinciden
*.md
en un directorio - Ejecute
COMMAND inputfile.md > ~/newdirectory/inputfile.md.conf
dondeinputfile
está la misma cadena en cada iteración.
¡Gracias!
Respuesta1
Hagas lo que hagas, necesitarás invocar un shell para realizar la redirección de la salida del comando a un archivo cuya ubicación depende del find
resultado.
find ./ *.md -not -path './/.git/*' -exec sh -c 'COMMAND "$0" > ~/wiki/newdirectory/"${0##*/}.cong"' {} \;
No sustituya {}
dentro del script de shell. Esto no es compatible con todos los sistemas, e incluso donde lo es, no funcionaría en general, ya que trataría el nombre del archivo como una parte de la sintaxis del shell, por ejemplo, un archivo llamado ;rm -rf ~;.md
haría que usted borrara todos sus archivos.
${0##*/}
utiliza manipulación pura de cadenas para obtener el nombre base del archivo. También podrías usar $(basename -- "$0")
.
Respuesta2
Si find
aceptas -execdir
, esto debería funcionar.
find . -name '*.md' -not -path './/.git/*' -execdir COMMAND {} > ~/wiki/newdirectory/{}.cong \;
Alternativamente
find . -name '*.md' -not -path './/.git/*' -exec bash -c \
'for f; do COMMAND "$f" > ~/wiki/newdirectory/"${f##*/}".cong; done' _ {} +