¿Alguien tiene un script de shell de plantilla para hacer algo con lsuna lista de nombres de directorio y recorrer cada uno y hacer algo?
Estoy planeando hacer ls -1d */para obtener la lista de nombres de directorio.
fuente
¿Alguien tiene un script de shell de plantilla para hacer algo con lsuna lista de nombres de directorio y recorrer cada uno y hacer algo?
Estoy planeando hacer ls -1d */para obtener la lista de nombres de directorio.
Editado para no usar ls donde lo haría un globo, como sugirieron @ shawn-j-goff y otros.
Solo usa un for..do..donebucle:
for f in *; do
echo "File -> $f"
done
Puede reemplazar el *con *.txto cualquier otro pegote que devuelve una lista (de los archivos, directorios o lo que fuera), un comando que genera una lista, por ejemplo, $(cat filelist.txt)o en realidad sustituirla por una lista.
Dentro del dobucle, solo se refiere a la variable del bucle con el prefijo del signo de dólar ( $fen el ejemplo anterior). Puedes echohacerlo o hacer cualquier otra cosa que quieras.
Por ejemplo, para cambiar el nombre de todos los .xmlarchivos en el directorio actual a .txt:
for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done
O incluso mejor, si está usando Bash, puede usar expansiones de parámetros de Bash en lugar de generar una subshell:
for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done
forbucles, y un error típico de tratar de analizar la salida dels. @ DanielA.White, podría considerar no aceptar esta respuesta si no fue útil (o es potencialmente engañosa), ya que, como dijo, está actuando en los directorios. La respuesta de Shawn J. Goff debería proporcionar una solución más sólida y funcional a su problema.lssalida , no debe leer la salida en unforbucle , debe usar en$()lugar de `` y Usar más comillas ™ . Estoy seguro de que @CoverosGene tenía buenas intenciones, pero esto es simplemente terrible.lsesls -1 | while read line; do stuff; done. Al menos ese no se romperá por espacios en blanco.mv -vusted no necesitaecho "moved $x -> $t"Usar la salida de
lspara obtener nombres de archivos es una mala idea . Puede provocar un mal funcionamiento e incluso scripts peligrosos. Esto se debe a un nombre de archivo puede contener cualquier carácter excepto/y elnullcarácter, ylsno utilizar cualquiera de esos caracteres como delimitadores, por lo que si un nombre de archivo tiene un espacio o una nueva línea, que va a obtener resultados inesperados.Hay dos formas muy buenas de iterar sobre archivos. Aquí, he usado simplemente
echopara demostrar que estoy haciendo algo con el nombre del archivo; Sin embargo, puedes usar cualquier cosa.El primero es usar las características de globbing nativas del shell.
El shell se expande
*/en argumentos separados queforlee el bucle; incluso si hay un espacio, una nueva línea o cualquier otro carácter extraño en el nombre del archivo,forverá cada nombre completo como una unidad atómica; no está analizando la lista de ninguna manera.Si desea ir recursivamente a subdirectorios, entonces esto no funcionará a menos que su shell tenga algunas características de globbing extendidas (como
bash'sglobstar. Si su shell no tiene estas características, o si quiere asegurarse de que su script funcionará en una variedad de sistemas, entonces la siguiente opción es usarfind.Aquí, el
findcomando llamaráechoy le pasará un argumento del nombre del archivo. Hace esto una vez por cada archivo que encuentra. Al igual que con el ejemplo anterior, no se analiza una lista de nombres de archivo; en cambio, un fileneame se envía completamente como argumento.La sintaxis del
-execargumento parece un poco divertida.findtoma el primer argumento después-execy lo trata como el programa a ejecutar, y cada argumento posterior, toma como un argumento para pasar a ese programa. Hay dos argumentos especiales que-exechay que ver. El primero es{}; este argumento se reemplaza con un nombre de archivo quefindgenera las partes anteriores . El segundo es;, que permitefindsaber que este es el final de la lista de argumentos para pasar al programa;findnecesita esto porque puede continuar con más argumentos destinadosfindy no destinados al programa ejecutado. La razón de esto\es que la cáscara también trata;especialmente: representa el final de un comando, por lo que debemos escapar para que el shell lo ofrezca como argumento enfindlugar de consumirlo por sí mismo; Otra forma de hacer que el shell no lo trate especialmente es ponerlo entre comillas:';'funciona tan bien como\;para este propósito.fuente
find. Hay magia que se puede hacer, e incluso las limitaciones percibidas-execse pueden solucionar. La-print0opción también es valiosa para usar conxargs.Para los archivos con espacios, deberá asegurarse de citar la variable como:
o puede cambiar la variable de entorno del separador de campo de entrada (IFS):
Finalmente, dependiendo de lo que esté haciendo, es posible que ni siquiera necesite el ls:
fuente
\nes insuficiente. Nunca es una buena idea recomendar analizar la salida dels.Si tiene instalado GNU Parallel http://www.gnu.org/software/parallel/ , puede hacer esto:
Para cambiar el nombre de todo .txt a .xml:
Mire el video de introducción de GNU Parallel para obtener más información: http://www.youtube.com/watch?v=OpaiGYxkSuQ
fuente
Solo para agregar a la respuesta de CoverosGene, aquí hay una manera de enumerar solo los nombres de directorio:
fuente
¿Por qué no establecer IFS en una nueva línea y luego capturar la salida de
lsen una matriz? Establecer IFS en nueva línea debería resolver problemas con caracteres divertidos en los nombres de archivo; usarlspuede ser bueno porque tiene una función de clasificación incorporada.(En las pruebas, tuve problemas para configurar IFS
\npero funciona como backspace de nueva línea, como se sugiere en otro lugar aquí):Por ejemplo (suponiendo
lsque se pasa el patrón de búsqueda deseado$1):Esto es especialmente útil en OS X, por ejemplo, para capturar una lista de archivos ordenados por fecha de creación (más antigua a más reciente), el
lscomando esls -t -U -r.fuente
\nes insuficiente. Las únicas soluciones válidas utilizan un bucle for con expansión de nombre de ruta, ofind.Así es como lo hago, pero probablemente hay formas más eficientes.
fuente
ls | while read i; do echo filename: $i; done