image - panda - tinypng photoshop plugin
Arrastre y suelte el archivo por lotes para varios archivos? (4)
Escribí un archivo por lotes para usar PngCrush para optimizar una imagen .png cuando la arrastro y la coloco en el archivo por lotes.
En la sección siguiente, escribí sobre lo que pensé que sería una buena actualización del archivo por lotes.
Mi pregunta es: ¿ es posible crear un archivo por lotes como lo hice en la publicación, pero capaz de optimizar varias imágenes a la vez? Arrastre y suelte varios archivos .png en él? (y la salida será algo así como new.png, new (1) .png, new (2) .png, etc ...
Arrastrar y soltar de forma segura no es tan sencillo con el lote.
Tratar con %1
, shift
o %*
podría fallar, porque el explorador no es muy inteligente, mientras que al citar los nombres de los archivos, solo se citan los nombres de los archivos con espacios.
Pero los archivos como Cool&stuff.png
no son citados por el explorador por lo que se obtiene una línea de cmd como
pngCr.bat Cool&stuff.png
Por lo tanto, en %1
solo está Cool
incluso en %*
solo es Cool
, pero después de que termine el lote, cmd.exe intenta ejecutar stuff.png
(y fallará).
Para manejar esto, puede acceder a los parámetros con !cmdcmdline!
en lugar de %1
.. %n
, y para eludir un posible error al final de la ejecución, una simple exit
podría ayudar.
@echo off
setlocal ENABLEDELAYEDEXPANSION
rem Take the cmd-line, remove all until the first parameter
set "params=!cmdcmdline:~0,-1!"
set "params=!params:*" =!"
set count=0
rem Split the parameters on spaces but respect the quotes
for %%G IN (!params!) do (
set /a count+=1
set "item_!count!=%%~G"
rem echo !count! %%~G
)
rem list the parameters
for /L %%n in (1,1,!count!) DO (
echo %%n #!item_%%n!#
)
pause
REM ** The exit is important, so the cmd.ex doesn''t try to execute commands after ampersands
exit
Por cierto. hay un límite de línea para operaciones de arrastrar y colocar de ~ 2048 caracteres, a pesar del límite de línea de lote "estándar" de ~ 8192 caracteres.
En cuanto a cada archivo, se pasa la ruta completa, este límite se puede alcanzar con pocos archivos.
No necesita un script por lotes para optimizar varios PNG, todo lo que necesita es el comodín:
pngcrush -d "crushed" *.png
Eso atrapará todos los PNG en el directorio actual y los moverá a un subdirector llamado "aplastado". Agregaría la bandera de -brute para afeitar algunos bytes más.
pngcrush -d "crushed" -brute *.png
Estoy publicando esto porque no parece estar bien documentado o es ampliamente conocido, y porque a la larga puede ser más fácil que escribir y mantener un archivo por lotes arrastrado y soltado.
Sí, por supuesto, esto es posible. Al arrastrar varios archivos en un archivo por lotes, obtiene la lista de archivos eliminados como una lista separada por espacios. Puede verificar esto con el siguiente lote simple:
@echo %*
@pause
Ahora, tú tienes dos opciones:
PngCrush ya puede manejar múltiples nombres de archivo dados a él en la línea de comando. En este caso, todo lo que tendrías que hacer sería pasar
%*
a PngCrush en lugar de solo%1
(como probablemente lo hagas ahora):@pngcrush %*
%*
contiene todos los argumentos en el archivo por lotes, por lo que esta es una forma conveniente de pasar todos los argumentos a otro programa. Sin embargo, hay que tener cuidado con los archivos nombrados como opciones de PngCrush. Los geeks de UNIX sabrán ese problema :-)Sin embargo, después de leer su publicación describiendo su técnica, esto no funcionará correctamente mientras está escribiendo el archivo comprimido en
new.png
. Una mala idea si está manejando varios archivos a la vez, ya que solo puede haber unnew.png
:-). Pero simplemente probé que PngCrush maneja varios archivos muy bien, así que si no te importa una actualización en el lugar de los archivos, entonces poner@pngcrush -reduce -brute %*
en su lote hará el trabajo (siguiendo su artículo original).
PngCrush no manejará varios archivos o si desea escribir cada imagen en un nuevo archivo después de la compresión. En este caso, sigue con su rutina de "un archivo a la vez" pero realiza un bucle sobre los argumentos de entrada. En este caso, es más fácil crear un pequeño bucle y
shift
los argumentos cada vez que procesa uno:@echo off if [%1]==[] goto :eof :loop pngcrush -reduce -brute %1 "%~dpn1_new%~x1" shift if not [%1]==[] goto loop
Lo que estamos haciendo aquí es simple: primero omitimos todo el lote si se ejecuta sin argumentos, luego definimos una etiqueta para saltar a:
loop
. En el interior, simplemente ejecutamos PngCrush en el primer argumento, dando al archivo comprimido un nuevo nombre. Es posible que desee leer la sintaxis de disección de ruta que utilicé aquí en lahelp call
. Básicamente lo que hago aquí es nombrar el archivo exactamente como antes; Solo coloco "_new" al final del nombre del archivo (antes de la extensión).%~dpn1
expande para conducir, ruta y nombre de archivo (sin extensión), mientras que%~x1
expande a la extensión, incluido el punto.ETA: Eep, acabo de leer el resultado deseado con new.png, new (1) .png, etc. En este caso, no necesitamos ninguna disección de ruta de fantasía, pero tenemos otros problemas que preocuparnos.
La forma más fácil sería simplemente iniciar un contador en 0 antes de procesar el primer archivo y aumentarlo cada vez que procesemos otro:
@echo off if [%1]==[] goto :eof set n=0 :loop if %n%==0 ( pngcrush -reduce -brute %1 new.png ) else ( pngcrush -reduce -brute %1 new^(%n%^).png ) shift set /a n+=1 if not [%1]==[] goto loop
%n%
es nuestro contador aquí y manejamos el caso donden
es 0 escribiendo el resultado ennew.png
, en lugar denew(0).png
.Este enfoque tiene problemas, sin embargo. Si ya hay archivos llamados
new.png
onew(x).png
, probablemente los golpees. No está bien. Entonces, tenemos que hacer algo diferente y verificar si realmente podemos usar los nombres de los archivos:rem check for new.png if exist new.png (set n=1) else (set n=0 & goto loop) rem check for numbered new(x).png :checkloop if not exist new^(%n%^).png goto loop set /a n+=1 goto checkloop
El resto del programa permanece igual, incluido el ciclo normal. Pero ahora comenzamos con el primer nombre de archivo no utilizado y evitamos sobrescribir los archivos que ya están allí.
Siéntase libre de adaptarse según sea necesario.
FOR %%A IN (%*) DO (
REM Now your batch file handles %%A instead of %1
REM No need to use SHIFT anymore.
ECHO %%A
)
Y para diferenciar entre archivos y carpetas descartadas, puede usar esto:
FOR %%I IN (%*) DO (
ECHO.%%~aI | FIND "d" >NUL
IF ERRORLEVEL 1 (
REM Processing Dropped Files
CALL :_jobF "%%~fI"
) ELSE (
REM Processing Dropped Folders
CALL :_jobD "%%~fI"
)
)