¿Cómo puedo usar comodines de estilo ms-dos con ls y mv?

9

Tengo la desgracia de provenir de un entorno de MS-DOS, pero al menos me hace apreciar lo mucho más poderoso que es Linux. He estado trabajando para que mi Linux-Fu esté a la par, pero hay un par de cosas que podrían hacerse con DOS que no estoy seguro de cómo lograr con más facilidad con Linux:

Cambiar el nombre de varios archivos: usar dos comodines

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\>rename *.txt *.bak

c:\> dir

Directory of c:\
    file1.bak
    file2.bak
    file3.bak
    file4.bak

Sé que podría usar find -execaquí, pero es posible usar una sintaxis más corta, ¿tal vez mvcon algunas banderas o sintaxis especiales? Supongo que la clave para esto es el segundo * comodín, ya que Linux no debería tener un problema con el primero (es decir, sé cómo seleccionar los archivos que quiero renombrar usando comodines)

Cambiar el nombre de un solo archivo: uso de un comodín

c:\> dir

Directory of c:\
    file1.txt

c:\>rename file1.txt *.bak

c:\> dir

Directory of c:\
    file1.bak

Esto sería especialmente útil al renombrar nombres de archivo largos y difíciles de manejar. Pensé que quizás podría usar mv file1.txt $1.bakpara terminar con file1.txt.baklo que también sería aceptable, pero no estoy seguro de que pueda hacer referencia al $1parámetro en línea con un comando de shell. Nuevamente, en este caso particular, es conveniente cómo ms-dos bastardiza el *comodín para ser utilizado como una especie de coincidencia de captura / reemplazo para parte del nombre de archivo.

Filtrado de listados de directorio con un comodín

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt
    text.txt
    \temp       (directory) 

c:\> dir file*

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\> t*

Directory of c:\
    text.txt
    \temp       (directory) 

No estoy seguro de cuál es la sintaxis correcta para hacerlo ls, o si es posible. Si hice algo así ls t*, volverá a aparecer en los directorios a partir de t. Mi solución alternativa ha estado usando find . --max-depth 1 -iname "t*"o algo así ls -al | grep t, ninguno de los cuales es tan corto y simple como dir t*es.

Finalmente, sé que puedo configurar alias para acortar estos comandos largos, pero me gustaría aprender algunos linux-fu listos para usar para hacer estas cosas porque a veces estás conectado a un sistema remoto o estás trabajando En una nueva máquina.

Entonces, ¿cómo puedo mvy lsarchivos de la misma manera que solía diry renamearchivos?

cwd
fuente

Respuestas:

15

Una de las diferencias fundamentales entre cmdlos shells de Windows y POSIX es quién es responsable de las expansiones de comodines. Los shells realizan todas las expansiones necesarias antes de comenzar los comandos reales que solicitó. pasa cmd principalmente los patrones comodín a los comandos sin modificar. (Digo sobre todo, ya que creo que hay excepciones, y las variables de entorno se expanden en la mayoría de las circunstancias). Esto hace que escribir una renameque funcione con la misma sintaxis que en cmdbastante complicado.

Pero hay una renamepara Linux: con argumentos completamente diferentes, consulte la página de manual (que es un poco breve en mi sistema y renameproviene del util-linuxpaquete en mi sistema, que debería estar ampliamente disponible). Su primer cambio de nombre se haría así:

rename .txt .bak *.txt

Tenga en cuenta que el shell realiza la *expansión, por lo que renameen realidad cree que se invocó de esta manera:

rename .txt .bak file1.txt file2.txt file3.txt ...

Entonces puedes adivinar la versión de un solo archivo:

rename .txt .bak file1.txt

Si no desea usarlo renamepero implementarlo usted mismo, puede crear una función para eso. Suponiendo que solo desea cambiar la extensión del archivo, y para cambiar el nombre de un solo archivo, mire esto:

$ function chext() {
  newext="$1"
  file="$2"
  newfile="${file%.*}$newext"
  echo mv "$file" "$newfile"
}
$ chext .csv test.txt
mv text.txt text.csv

$newfilese construye utilizando una eliminación de subcadena para quitar la extensión original, luego concatena la nueva extensión. Puede extender esa función para manejar múltiples archivos con relativa facilidad.


En cuanto a su lspregunta, use el -dinterruptor. Esto evitará que se lsenumeren los contenidos de los directorios.

Manifestación:

$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:29 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.csv
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Cambiar nombre de comodín

$ rename .csv .txt f*
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Cambiar nombre de archivo único

$ rename .txt .csv f1.txt 
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

El valor por defecto ls

$ ls -l t*
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

test:
total 0
-rw-r--r-- 1 owner users 0 Jan  7 17:33 dont_show_me_please

ls que no inspecciona directorios

$ ls -ld t*
drwxr-xr-x 2 owner users 4096 Jan  7 17:33 test
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv
Estera
fuente
¡muy agradable! ¡Creo que acabo de subir un cinturón con mi linux-fu! ¡Gracias!
cwd
Sugerencia para avanzar un poco con esto (y evitar dificultades): use funciones simples o scripts para ver qué sucede cuando lo hace somefunc *.Extsi ese patrón no coincide con ningún archivo, y juegue con comillas para ver si logra pasar un patrón ( sin tenerlo expandido) entre funciones. Consejo de seguridad: no lo use en rmningún lugar mientras experimenta con la expansión globular / shell :-)
Mat
4

Una cosa a tener en cuenta cuando se trata de comodines es que el shell los expande. La aplicación no sabe si usó comodines o escribió los nombres. Por ejemplo, si escribe rename *.txt *.bak, el renamecomando ve algo así rename file1.txt file2.txt existingfile.bak. Esa no es suficiente información para continuar.

lsPrimero me ocuparé de la pregunta , porque es más simple. Si todo lo que quiere son los nombres coincidentes, entonces no los necesita ls, porque el shell ya está haciendo la expansión.

echo t*

Si desea obtener más información sobre los archivos, pase la -dopción a ls, para decirle que no enumere el contenido de los directorios.

ls -ld t*

No existe una utilidad estándar para renombrar archivos, porque los primeros sistemas unix no venían con uno. El método portátil para cambiar el nombre de los archivos utiliza un bucle y es un poco detallado:

for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done

Hay varias utilidades comunes para cambiar el nombre de los archivos, ninguno de los cuales está garantizado para instalarse en un sistema Unix determinado, pero todos son fáciles de instalar. Aquí están los principales:

  • renamede la util-linuxsuite, disponible en todos los sistemas Linux no integrados (y en ningún otro lugar). En Debian y derivados (incluido Ubuntu), este comando se llama rename.ul. Siempre que no se produzca .txtotra extensión que no sea la extensión final, puede escribir

    rename .txt .bak *.txt
    
  • renamees un script de Perl que Debian y sus derivados se envían como /usr/bin/rename. Puede cambiar el nombre de los archivos de acuerdo con los comandos arbitrarios de Perl.

    rename 's/\.txt\z/\.bak/' *.txt
    
  • mmv, que puede cambiar el nombre, copiar y vincular archivos de acuerdo con varios patrones basados ​​en nombres y tiene muchas opciones relacionadas con lo que sucede si ya existe un nombre de destino. Tenga en cuenta que debe usar comillas para proteger los comodines de la expansión del shell.

    mmv '*.txt' '#1.txt'
    
  • zmves una función zsh , disponible si y solo si su shell es zsh. Puede hacer coincidir patrones zsh arbitrarios (por lo que puede hacer coincidir nombres de archivos de acuerdo con expresiones regulares arbitrarias, no solo comodines, y puede hacer coincidir archivos por otros criterios como fechas y tamaños). zmvTambién puede copiar y vincular.

    zmv '(*).txt' '$1.txt'
    

Si tiene algún control sobre las máquinas que usa, mi recomendación es usar zsh como su shell (tiene otros beneficios sobre bash) y poner estas líneas en su ~/.zshrc:

autoload -U zmv
alias zmv='noglob zmv -w'
alias zcp='zmv -C'
alias zln='zmv -L'
alias zsy='zmv -Ls'

noglobes una función zsh que le dice al shell que no expanda comodines en el argumento del comando. De esta manera puede escribir zmv *.txt \$1.txt(siempre necesitará protegerlo $en un texto de reemplazo).

Gilles 'SO- deja de ser malvado'
fuente