2

For the purposes of saving space and organizing, I'm zipping bunch of files in my local and networked folders. They are mainly CAD files, like stp, igs, etc.

There are already existing zip files and some are extracted by other users, but the zip file still exists on the folders, which eats up space.

Is there a command line zip, rar, 7z. etc. to find out if an archive file contains only 1 file?

I'd like to figure this out as I'll extract the archives with single files in to the current directory whilst extracting archives with 1+ files to \archivename\ folder. Otherwise one folder with 30 STP files, will suddenly have 30 folders and 30 files extracted in them which I don't want.

I currently use a batch file with WinRAR to extract and another program to check for duplicates, then WinRAR batch to re-zip them based on file extension. (Reason: people use different archive methods and there are duplicates of files all over.)

Sample batch files:

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

Once I can check for number of files in a zip, I'll add a recursive function.

I can use NTFS compression, but I also want to organize the folders, some folder have 1000 files in them, I surely want to reduce that to 1. These are mainly for archiving purposes.

Any help or thought would be appreciated.

4

2 回答 2

3

我建议为此任务使用以下注释批处理文件:

@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它是一个 GUI 应用程序,因此不支持将存档文件的内容列出到控制台作为Rar.exe支持。

控制台版本Rar.exe和免费控制台应用程序UnRAR.exe都支持列出存档文件内容以处理各种格式的STDOUT

WinRAR.exeRar.exe/之间支持的命令的差异UnRAR.exe可以通过在 WinRAR 中打开帮助来查看,方法是在菜单项帮助主题上单击菜单帮助,在帮助选项卡上打开内容列表项命令行模式,打开列表项命令,单击列表项按字母顺序排列的命令列表 ,并将此列表与WinRAR的程序文件文件夹中的文本文件中列出和描述的命令进行比较,该文件是控制台版本的手册。Rar.txt

Rar.txt列出并描述:

l[t[a],b] ... 列出存档内容 [技术 [全部],裸露]
v[t[a],b] ... 详细列出存档内容 [技术 [全部],裸露]。

WinRAR的帮助是否包含命令l或命令v

当然也可以使用命令在每个 *.rar 文件上运行Rar.exe或运行,计算上面批处理文件中输出的行数以计算文件并根据行数提取 *.rar 存档文件到当前目录(仅 1 行)或子目录。UnRAR.exelb

但应该考虑到,在使用裸列表格式并且只有 1 行输出时,该行可以是存档文件的名称或存档的空文件夹的名称。解决方案将使用标准列表命令并更多地分析属性,因为目录具有属性D而文件没有此属性。

对于 *.7z 和 *.zip 文件,必须使用7z.exe或进行编码7za.exe7-Zip的帮助还描述了可用的命令和开关,如WinRAR的帮助。

但是与发布的解决方案相比,所有这些努力都没有多大意义,因为必须完全提取存档文件并且移动文件非常快,因为文件分配表中的条目被修改并且没有数据被复制或移动全部。

首先单独运行7-ZipRar仅列出每个存档文件内容,分析列表,然后在存档文件上再次运行7-ZipRar以进行提取比仅运行WinRAR 3 次(或更少)以提取所有文件要慢得多存档,然后移动一些文件并删除一些目录。

要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

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

另请参阅 Microsoft TechNet 文章使用命令重定向运算符

于 2017-02-04T16:21:34.217 回答
2

以问题文字为例,以下批次使用 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
于 2017-02-04T18:31:43.287 回答