ls -1
enumera mis elementos así:
foo.png
bar.png
foobar.png
...
Quiero que aparezca en la lista sin los siguientes .png
:
foo
bar
foobar
...
(el directorio solo contiene .png
archivos)
¿Alguien puede decirme cómo usar grep
en este caso?
Propósito: Tengo un archivo de texto donde se enumeran todos los nombres sin la extensión. Quiero hacer un script que compare el archivo de texto con la carpeta para ver qué archivo falta.
.
en ellos. Aunque la convención dice para nombrar sus archivos con.png
al final, no hay ninguna razón por qué no puedo tener un archivo PNG nombradofoo.zip
omy.picture.20160518
o simplementemypic
.ls
y canalizar la salida de ,ls
yfind
principalmente debido a la posibilidad de incurrir ennewline
`tab char en el nombre del archivo. Si el nombre de archivo esThe new art of working on .png\NEWLINE files and other formats
muchas de las soluciones propuestas creará problemas.Respuestas:
Solo necesita el shell para este trabajo.
POSIXY:
Con
zsh
:fuente
printf
;echo ${f%.png}
Será suficiente.El
sed
comando elimina (es decir, reemplaza con la cadena vacía) cualquier cadena que se.png
encuentre al final de un nombre de archivo.Se
.
escapa como\.
para que se interpretesed
como un.
carácter literal en lugar de la expresión regular.
(lo que significa que coincide con cualquier carácter). El$
es el ancla de fin de línea, por lo que no coincide.png
en el medio de un nombre de archivo.fuente
sed 's/\.[^.]*$//'
-1
no es necesario, siendo el predeterminado aquí.-1
debe especificarse. Es solo el valor predeterminado cuando la tubería está encendida, lo cual es una sorpresa oculta para algunos. Entonces hacerlo explícito ayuda a la comprensión. También hago esto en mis scripts para saber qué tipo de salida estoy esperando..png
) antes de un carácter de nueva línea, borrará incluso eso.png
y no solo el último. Es mejor evitar canalizar y analizar la salida de ls, reserva sorpresas a menudo bien ocultas ... (algunas palabras y referencias más en la respuesta).Si solo quieres usar bash:
Debe buscar
grep
cuando intente encontrar coincidencias, no para eliminar / sustituir esosed
es más apropiado:Una vez que decida que necesita crear algunos subdirectorios para poner orden en sus archivos PNG, puede cambiarlo fácilmente a:
fuente
find
hilo desed
solución puede presentar algunos problemas si encuentra un archivo con la tecla (.png
) como parte del nombre y justo antes de un carácter de nueva línea. Es mejor evitar canalizar y analizar la salida defind
ols
, reserva sorpresas a menudo bien escondidas ... (algunas palabras y referencias más en la respuesta).find
con algo comoecho
en el último ejemplo. No está claro qué propósitofind
sirve allí y los resultados dependen de la estructura del directorio (es decir, si tiene un directoriofiles.png
)Yo iría por
basename
(asumiendo la implementación de GNU):fuente
-z
(o--zero
) de GNU basename para producir una salida separada por NUL (en lugar de nueva línea).Otra respuesta muy similar (me sorprende que esta variante en particular aún no haya aparecido) es:
-1
opciónls
, yals
que supone que si la salida estándar no es una terminal (es una tubería, en este caso).-n
opción ased
significa 'no imprimir la línea por defecto'/p
opción al final de la sustitución significa '... e imprima esta línea si se realizó una sustitución'.El efecto neto de eso es imprimir solo aquellas líneas que terminan en
.png
, con el.png
eliminado. Es decir, esto también atiende a la leve generalización de la pregunta del OP, donde el directorio no contiene solo.png
archivos.La
sed -n
técnica a menudo es útil en casos en los que de otro modo podría usar grep + sed.fuente
.png
) antes del carácter de nueva línea: en ese caso, imprimirá esa parte sin png, sin borrar solo la última parte. A menudo se sugiere evitar analizar (y canalizar) la salidals
porque los problemas pueden ocultarse justo donde no estás pensando ...find
o, posiblemente mejor, use un lenguaje más poderoso quesh
para administrarlos (el hecho de quesh
pueda hacer todo no significa que sea la mejor opción en cada caso). La carcasa está diseñada para usabilidad primero.ls
, pero se trata de problemas futuros. A menudo creamos scripts que usaremos más tarde, cuando ya olvidaremos su límite ... (es humano, es habitual). I propuesto unfind
ejemplo (con-exec
y sin tubo), incluso si considero una mejor (debido shell puro) responde a la de uno cuonglm , sólida y posix compatible.locate
omake
sobre ellos.Puede usar solo comandos BASH para hacer eso (sin herramientas externas).
Esto es útil cuando no tiene / usr / bin y funciona bien para nombres de archivo como this.is.image.png y para todas las extensiones.
fuente
No es seguro analizar
ls
o canalizarfind
[ 1 , 2 ]No es seguro analizar (y canalizar) la salida de
ls
ofind
, principalmente porque es posible encontrar en los nombres de archivo caracteres no habituales como la nueva línea , la pestaña ... Aquí funcionará un ciclo de shell puro [ cuonglm ] .Incluso el
find
comando no conectado con la opción-exec
funcionará:Actualizaciones / Notas : puede usar
find .
para buscar incluso los archivos ocultos, ofind ./*.png
para obtener solo los no ocultos. Confind *.png -exec ...
usted puede tener un problema en el caso de que estuviera presente un archivo llamado.png
porque find lo obtendrá como una opción. Puede agregar-maxdepth 0
para evitar descender en directorios nombrados comoDir_01.png
, ofind ./*.png -prune -exec ...
cuando maxdepth no está permitido (gracias Stéphane). Si desea evitar enumerar esos directorios, debe agregar la opción-type f
(que también excluiría otros tipos de archivos no regulares). Eche un vistazo alman
para obtener un panorama más completo sobre todas las opciones disponibles, y recuerde verificar cuándo son compatibles con POSIX, para una mejor portabilidad.Algunas palabras mas
Puede suceder, por ejemplo, que al copiar el título de un documento y pegarlo en el nombre del archivo, una o más líneas nuevas terminen en el nombre del archivo. Podemos ser tan desafortunados que un título puede contener incluso la clave que tenemos que usar justo antes de una nueva línea:
Si desea probar, puede crear nombres de archivo como este con los comandos
El simple
/bin/ls *png
saldrá en?
lugar de los caracteres no imprimiblesEn todos los casos en los que se quiere canalizar la salida del
ls
ofind
el comando siguiente tendrán ningún indicio de entender si la actual línea proviene de un nuevo nombre de archivo o si se sigue una nueva línea carácter en el precedente nombre de archivo . Un nombre desagradable en verdad, pero aún legal.Un ciclo de shell con un parámetro Parameter-Expansion,
${parameter%word}
en la variante conprintf
oecho
funcionará [ cuonglm ], [ Anthon1 ] .Desde la página del manual de la expansión de parámetros de Shell [ 3 ]
fuente
find
comando son una variable de bit (por ejemplo, si hay un directorio llamadofiles.png
)bash 4.3.11
, dash 0.5.7-4, zsh (cuando sea necesario) 5.0.2. Siéntase libre de leer esta publicación que agrega algo más. Estoy de acuerdo con la nota de canalizar la salida defind
, para esto sugerí expresamente-exec
, y escribí en el título.:-)
.ls
no hay ningún problema cuando la salida se canaliza o se redirige, pero como se menciona en wiki, puede que no funcione para todos. La mayoría solo insertará los?
caracteres especiales en lugar de cuando la salida se envíe al terminal. es decir, hacerecho *.png | od -c
yls *.png | od -c
. El problema de la nueva línea no es un problemals
, es un problema con cualquier comando que no termina nula en ambos lados de la tubería.printf "${f%.png}\n"
Está Mal. El primer argumento es el formato, no debe usar datos variables allí. Incluso puede verse como una vulnerabilidad DoS (%1000000000s.png
por ejemplo, intente con un archivo).find ./*.png -prune -exec...
o tendría problemas con los nombres de archivo que comienzan con-
(y los archivos de tipo directorio, tenga en cuenta que-maxdepth
no es portátil)no fue suficiente?
o en general, esto
eliminará todas las extensiones
fuente
-1
no es necesario, siendo el predeterminado aquí.ls
hace de todos modos sin esa opción cuando su salida no es una terminal, que es el caso aquí.Uso
rev
:rev
invierte todas las cadenas (líneas); cortas todo después del primer '.' y rev revierte el remanente.Si quieres
grep
'alma':fuente
-1
no es necesario, siendo el predeterminado aquí.My.2016.Summer.Vacation.png
cut -f 2-
.png
y una nueva línea justo después ... Se sugiere evitar analizarls
porque le encanta ocultar bien las sorpresas ... :-)Si supiera que el directorio solo tiene archivos con .png como extensión, simplemente habría ejecutado:
ls | awk -F. '{print $1}'
Esto devolverá el primer "campo" para cualquier cosa donde haya un nombre de archivo. Extensión.
Ejemplo:
fuente
.
,Image.1.png
e incluso en los que no tienen nombres agradables , con caracteres especiales dentro. como el salto de línea o el que va a utilizar como (entrada) separador de registro enawk
,RS
. Se sugiere evitar analizar lals
salida porque le encanta ocultar el problema que surgirá cuando no lo espere. Puede leer más en las referencias 1 o 2 . Por cierto, es agradable la idea de usar awk ... Puse algunos ejemplos en una respuesta..
en\.
el interior de lased -e 's/\.png$//'
, pero por lo que se convierte en una respuesta acaba de escribir. :-( nota2 puede intentar usarawk
con algo comols | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}'
... pero siempre tendrá el problema de que awk no puede saber si la línea que está llegando sigue o no una nueva línea dentro del nombre del archivo. Intenté decir mejor en mi respuesta .de acuerdo con su comentario "Tengo un archivo de texto donde se enumeran todos los nombres sin la extensión. Quiero hacer un script PHP que compare el archivo de texto con la carpeta para ver qué archivo falta":
y al revés:
fuente
ls -l | sed 's/\.png$//'
Es el método más preciso como lo destaca @roaima. Sin los escapados
\.png
archivos con el nombrea_png.png
sería catalogado como:a_
.fuente
ls -l
, como lo hace, da los detalles del archivo, eso no es lo que el OP preguntó.Una línea de shell simple (ksh, bash o zsh; no dash):
Una función simple (desde Sin extensión):
O una función que elimina cualquier extensión dada (png por defecto):
Usar como:
Si la salida es un asterisco
*
, no existe ningún archivo con esa extensión.fuente
Puede probar el siguiente feed awk la salida de ls su superator es el "." y como todos tus archivos tendrán nombre.png imprimes la primera columna:
ls | awk -F"." '{print $1}'
fuente
Si tiene acceso a sed, esto es mejor ya que eliminará la última extensión de archivo, sin importar cuál sea (png, jpg, tiff, etc.)
fuente
this.is.a.dotty.txt
. Intenta en sus/\.[^.]*$//
lugar.