Как проверить, содержит ли файл zip или rar 1 или более файлов?

В целях экономии места и организации я архивирую кучу файлов в своих локальных и сетевых папках. В основном это файлы САПР, такие как stp, igs и т. д.

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

Есть ли в командной строке zip, rar, 7z. и т. д., чтобы узнать, содержит ли файл архива только 1 файл?

Я хотел бы выяснить это, поскольку я буду извлекать архивы с отдельными файлами в текущий каталог, а архивы с 1+ файлами - в папку \archivename\. В противном случае в одной папке с 30 файлами STP внезапно будет 30 папок и 30 файлов, извлеченных из них, чего я не хочу.

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

Примеры пакетных файлов:

for /F "delims=," %%f in ('dir *.stp /B' ) do (%path% a -afzip -r- -m5 -ed -ep -or -tl -y -df "%%f".zip "%%f")

for /F "delims=;" %%f in ('dir *.7z /B /S' ) do (%path% x -OR -ilogC:\Users\XXXX\Desktop\myLog.txt "%%f" "%%~dpf"\"%%~nf"\)

Как только я смогу проверить количество файлов в zip, я добавлю рекурсивную функцию.

Я могу использовать сжатие NTFS, но я также хочу организовать папки, в некоторых папках есть 1000 файлов, я, конечно, хочу уменьшить их до 1. Это в основном для целей архивирования.

Любая помощь или мысль будут оценены.


person Ali    schedule 03.02.2017    source источник
comment
Я знаю, что Winzip может отображать содержимое zip-файла, не распаковывая его. Я бы предположил, что 7zip и Winrar тоже. Вы смотрели документацию к ним.   -  person Squashman    schedule 04.02.2017


Ответы (2)


Я предлагаю следующий закомментированный командный файл для этой задачи:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Extract all 7-Zip, RAR and ZIP archives in current directory into
rem subdirectories with name of archive file as name for subdirectory (-ad)
rem with running WinRAR for extraction in background (-ibck) which means
rem minimized to system tray with restoring also last access time (-tsa)
rem and creation time (-tsc) if existing in archive file and with skipping
rem files on extraction perhaps already present in the subdirectory with
rem same last modification time (-u), but overwriting automatically older
rem files in subdirectory if archive file contains an existing file with
rem a newer last modification time (-y) ignoring all errors (also -y).

for %%I in (7z rar zip) do "%ProgramFiles%\WinRAR\WinRAR.exe" x -ad -ibck -tsa -tsc -u -y *.%%I

rem If a subdirectory contains only 1 file, move that file to the current
rem directory with overwriting a perhaps already existing file with same
rem name in current directory and then remove the subdirectory.

for /D %%I in (*) do call :CheckSubDir "%%I"

rem Exit processing of the batch file without fall through to subroutine.
endlocal
goto :EOF

rem The subroutine CheckSubDir first checks for directories in directory
rem passed as parameter to the subroutine. A directory containing at
rem least one subdirectory is kept without any further processing.

rem If the directory does not contain a subdirectory, it searches for files
rem in the directory. If there are at least 2 files, the directory is kept
rem without any further processing.

rem But if the directory contains only 1 file, this file is moved to
rem current directory. Then the empty directory is deleted before exiting
rem the subroutine and continue batch file processing in calling loop.
rem Each directory containing no subdirectory and no file is removed, too.

:CheckSubDir
for /F "delims=" %%D in ('dir /AD /B "%~1\*" 2^>nul') do goto :EOF
setlocal EnableDelayedExpansion
set FileCount=0
for /F "delims=" %%F in ('dir /A-D /B "%~1\*" 2^>nul') do (
    set /A FileCount+=1
    if !FileCount! == 2 endlocal & goto :EOF
    set "FileName=%%F"
)
if %FileCount% == 1 move /Y "%~1\%FileName%" "%FileName%"
rd "%~1"
endlocal
goto :EOF

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

2>nul в последних двух циклах FOR перенаправляет сообщение об ошибке, выводимое командой DIR, на обработку STDERR в случае отсутствия каталога или файла на устройстве NUL, чтобы подавить его. Оператор перенаправления > должен быть экранирован символом вставки ^, чтобы он интерпретировался как оператор перенаправления при выполнении командной строки DIR, а не при анализе командной строки FOR.

WinRAR поддерживает множество типов архивов при извлечении. Но WinRAR.exe является приложением с графическим интерфейсом и поэтому не поддерживает вывод содержимого архивного файла на консоль, как это поддерживает Rar.exe.

Консольная версия Rar.exe, а также бесплатное консольное приложение UnRAR.exe поддерживают отображение содержимого файла архива для обработки STDOUT в различных форматах.

Эту разницу в поддерживаемых командах между WinRAR.exe и Rar.exe/UnRAR.exe можно увидеть, открыв в WinRAR справку, щелкнув в меню Справка пункт меню Темы справки, открыв на вкладке справки < strong>Содержимое элемента списка Режим командной строки, открытие элемента списка Команды, нажатие на элемент списка Алфавитный список команд и сравнение этот список с перечисленными и описанными командами находится в текстовом файле Rar.txt в папке программных файлов WinRAR, который является руководством для консольной версии.

Rar.txt перечисляет и описывает:

l[t[a],b] ... Перечислить содержимое архива [техническое [все], голое]
v[t[a],b] ... Подробно перечислить содержимое архива [техническое [все], голое] .

Справка WinRAR содержит ли команду l или команду v.

Конечно, также можно запустить Rar.exe или UnRAR.exe для каждого файла *.rar с помощью команды lb, подсчитать количество выводимых строк, как это сделано в приведенном выше пакетном файле, чтобы подсчитать файлы и извлечь архивный файл *.rar в зависимости от строки. считать в текущий каталог (только 1 строка) или в подкаталог.

Но следует учитывать, что при использовании формата чистого списка и выводе только 1 строки эта строка может быть именем файла в архиве или именем пустой папки в архиве. Решением будет использование стандартной команды списка и дополнительный анализ атрибутов, поскольку каталог имеет атрибут D, а файл не имеет этого атрибута.

А для файлов *.7z и *.zip то же самое нужно кодировать с помощью 7z.exe или 7za.exe. В справке 7-Zip также описаны доступные команды и переключатели, подобные справке WinRAR.

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

Запуск 7-Zip или Rar по отдельности, сначала просто список содержимого каждого архивного файла, анализ списка и запуск 7-Zip< /em> или Rar еще раз для файла архива для извлечения намного медленнее, чем запуск WinRAR всего 3 раза (или меньше) для извлечения всех архивов, а затем перемещения некоторых файлов и удаления некоторые каталоги.

Чтобы понять, какие команды используются и как они работают, откройте окно командной строки, выполните в нем следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.

  • call /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • move /?
  • rd /?
  • set /?
  • setlocal /?

См. также статью Microsoft TechNet Использование операторов перенаправления команд.

person Mofi    schedule 04.02.2017

Принимая вопрос буквально, следующий пакет использует 7z.exe (должен быть доступен через путь) список (l) -опция, чтобы получить количество файлов, включенных в архив, путем фильтрации последней строки.

@Echo off
Set Base=q:\Test
Pushd "%Base%"
For /f "delims=" %%A in (
  'Dir /B/S/A-D *.zip *.7z *.rar'
) Do For /f "tokens=5" %%B in (
  ' 7z.exe l "%%~A" ^| findstr "files$" '
) Do If %%B equ 1 (
  Echo Archive %%A contains 1 file
) else (
  Echo Archive %%A contains %%B files
)
Popd

Пример вывода:

Archive q:\Test\archiv.7z contains 135 files
Archive q:\Test\PoSh\powershellitunes\PowerScript-itunes.7z contains 1 file
Archive q:\Test\PoSh\_pdf_itextsharp\extract_pdf_pages_into_new_323689.zip contains 3 files
Archive q:\Test\_StackOverflow\Noodles\Filter0.8.zip contains 4 files
Archive q:\Test\2016\12\16\Path.rar contains 7 files
Archive q:\Test\_AllHelp.Win\allhelp.zip contains 7 files
Archive q:\Test\2017-02\pkzipc_40.rar contains 10 files
person Community    schedule 04.02.2017