Подтвердить что ты не робот

Перетащить пакетный файл для нескольких файлов?

Я написал пакетный файл для использования PngCrush для оптимизации изображения .png, когда я перетаскиваю его в пакетный файл.

В следующем разделе я написал о том, что, по моему мнению, будет хорошим обновлением в пакетном файле.

Мой вопрос: Можно ли создать пакетный файл, как я делал в сообщении, но способный одновременно оптимизировать несколько изображений? Перетащите несколько файлов .png на нем? (и выход будет чем-то вроде new.png, new (1).png, new (2).png и т.д.

4b9b3361

Ответ 1

Да, конечно, это возможно. При перетаскивании нескольких файлов в пакетном файле вы получаете список отброшенных файлов в виде списка, разделенного пробелами. Вы можете проверить это с помощью простой следующей партии:

@echo %*
@pause

Теперь у вас есть два варианта:

  • PngCrush уже может обрабатывать несколько имен файлов, предоставленных ему в командной строке. В этом случае все, что вам нужно сделать, это передать %* в PngCrush вместо просто %1 (как вы, вероятно, сейчас):

    @pngcrush %*
    

    %* содержит все аргументы командного файла, поэтому это удобный способ передать все аргументы в другую программу. Однако осторожно с файлами, названными как параметры PngCrush. UNIX-разработчики будут знать эту проблему: -)

    Однако, прочитав сообщение, описывающее вашу технику, это не будет работать должным образом, поскольку вы пишете сжатый файл на new.png. Плохая идея, если вы обрабатываете сразу несколько файлов, так как может быть только один new.png:-). Но я просто попробовал, что PngCrush отлично справляется с несколькими файлами, поэтому, если вы не возражаете против обновления на месте файлов, а затем помещаете

    @pngcrush -reduce -brute %*
    

    в вашу партию выполнит работу (после вашей оригинальной статьи).

  • PngCrush не будет обрабатывать несколько файлов или вы хотите записать каждое изображение в новый файл после сжатия. В этом случае вы будете придерживаться вашей "одного файла за раз", но вы будете перебирать входные аргументы. В этом случае проще всего построить небольшой цикл и shift аргументы каждый раз, когда вы его обрабатываете:

    @echo off
    if [%1]==[] goto :eof
    :loop
    pngcrush -reduce -brute %1 "%~dpn1_new%~x1"
    shift
    if not [%1]==[] goto loop
    

    То, что мы делаем здесь, просто: сначала мы пропустим всю партию, если она запущена без аргументов, затем мы определяем метку для перехода к: loop. Внутри мы просто запускаем PngCrush по первому аргументу, предоставляя сжатому файлу новое имя. Возможно, вы захотите прочитать синтаксис пересечения путей, который я использовал здесь, в help call. В основном то, что я делаю здесь, - это имя файла точно так же, как и раньше; Я просто вставляю "_new" в конец имени файла (перед расширением). %~dpn1 расширяется до имени диска, пути и файла (без расширения), а %~x1 расширяется до расширения, включая точку.

    ETA: Eep, я просто прочитал ваш желаемый результат с помощью new.png, new (1).png и т.д. В этом случае нам не нужны никакие расплывчатые пути, но у нас есть другие проблемы, о которых нужно заботиться.

    Самый простой способ - это просто запустить счетчик в 0, прежде чем обрабатывать первый файл и увеличивать его каждый раз, когда мы обрабатываем другой:

    @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% здесь наш счетчик, и мы обрабатываем случай, когда n равно 0, записывая результат в new.png вместо new(0).png.

    Однако этот подход имеет проблемы. Если уже есть файлы с именем new.png или new(x).png, тогда вы, вероятно, скроете их. Не хорошо. Поэтому нам нужно сделать что-то другое и проверить, можем ли мы фактически использовать имена файлов:

    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
    

    Остальная часть программы остается неизменной, включая обычный цикл. Но теперь мы начинаем с первого неиспользуемого имени файла и избегаем перезаписывания уже существующих файлов.

Не стесняйтесь при необходимости адаптироваться.

Ответ 2

Чтобы сделать перетаскивание безопасным способом, это не так просто с пакетом.

Работа с %1, shift или %* может завершиться неудачей, потому что проводник не очень умный, при цитировании имен файлов цитируются только имена файлов с пробелами.
Но файлы типа Cool&stuff.png не цитируются исследователем, поэтому вы получаете cmdline, например

pngCr.bat Cool&stuff.png

Так что в %1 только Cool даже в %* есть только Cool, но после окончания партии cmd.exe пытается выполнить stuff.png (и не получится).

Чтобы справиться с этим, вы можете получить доступ к параметрам с помощью !cmdcmdline! вместо %1.. %n, и для обхода потенциальной ошибки в конце выполнения может помочь простой exit.

@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

Btw. существует лимитный лимит для операций перетаскивания и уменьшения порядка 2048 символов, несмотря на "стандартное" ограничение линии партии ~ 8192 символов.
Что касается каждого файла, передается полный путь, этот предел может быть достигнут с несколькими файлами.

Ответ 3

FOR %%A IN (%*) DO (
    REM Now your batch file handles %%A instead of %1
    REM No need to use SHIFT anymore.
    ECHO %%A
)

И чтобы различать отброшенные файлы и папки, вы можете использовать это:

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"
    )
)

Ответ 4

Для оптимизации нескольких PNG вам не требуется пакет script, все, что вам нужно, это подстановочный знак:

pngcrush -d "crushed" *.png

Это будет pngcrush всех PNG в текущем каталоге и переместить их в sub-dir с именем "crushed". Я бы добавил флаг -brute, чтобы скорее сбрить еще несколько байтов.

pngcrush -d "crushed" -brute *.png

Я публикую это, потому что он, похоже, не хорошо документирован или широко известен, и потому, что вам может быть проще в конечном итоге, чем писать и поддерживать пакетный файл перетаскивания.