¿Alguien tiene un script de shell de plantilla para hacer algo con ls
una 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 ls
una 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..done
bucle:
for f in *; do
echo "File -> $f"
done
Puede reemplazar el *
con *.txt
o 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 do
bucle, solo se refiere a la variable del bucle con el prefijo del signo de dólar ( $f
en el ejemplo anterior). Puedes echo
hacerlo o hacer cualquier otra cosa que quieras.
Por ejemplo, para cambiar el nombre de todos los .xml
archivos 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
for
bucles, 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.ls
salida , no debe leer la salida en unfor
bucle , debe usar en$()
lugar de `` y Usar más comillas ™ . Estoy seguro de que @CoverosGene tenía buenas intenciones, pero esto es simplemente terrible.ls
esls -1 | while read line; do stuff; done
. Al menos ese no se romperá por espacios en blanco.mv -v
usted no necesitaecho "moved $x -> $t"
Usar la salida de
ls
para 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 elnull
carácter, yls
no 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
echo
para 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 quefor
lee el bucle; incluso si hay un espacio, una nueva línea o cualquier otro carácter extraño en el nombre del archivo,for
verá 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
find
comando llamaráecho
y 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
-exec
argumento parece un poco divertida.find
toma el primer argumento después-exec
y 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-exec
hay que ver. El primero es{}
; este argumento se reemplaza con un nombre de archivo quefind
genera las partes anteriores . El segundo es;
, que permitefind
saber que este es el final de la lista de argumentos para pasar al programa;find
necesita esto porque puede continuar con más argumentos destinadosfind
y 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 enfind
lugar 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-exec
se pueden solucionar. La-print0
opció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
\n
es 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
ls
en una matriz? Establecer IFS en nueva línea debería resolver problemas con caracteres divertidos en los nombres de archivo; usarls
puede ser bueno porque tiene una función de clasificación incorporada.(En las pruebas, tuve problemas para configurar IFS
\n
pero funciona como backspace de nueva línea, como se sugiere en otro lugar aquí):Por ejemplo (suponiendo
ls
que 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
ls
comando esls -t -U -r
.fuente
\n
es 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