如何将所有文件(文件夹中每个子文件夹中的最新文件除外)压缩到每个子文件夹一个ZIP文件中?

时间:2019-08-22 16:48:29

标签: batch-file command-line command zip 7zip

我正在尝试创建一个批处理脚本,该脚本将压缩每个子目录中除最近(或最近几个)之外的所有内容。我目前正在Windows中使用7-Zip进行尝试,但是从技术上讲,该目录位于Linux服务器上,因此欢迎针对Linux命令的任何建议。

目录结构如下:

Directory-Parent
 ---Sub-Directory-1
 --------File1
 --------File2
 --------File3
 ---Sub-Directory-2
 --------File1
 --------File2

我想在Directory-Parent级别运行一个批处理,它将在所有文件的每个子目录中创建一个zip文件,但最新文件除外(如果可能的话,则为几个)。我还想将年份添加到zip文件名的末尾。

结果将是:

Directory-Parent
 -Sub-Directory-1
 --------File1
 --------Sub-Directory-12019.zip
 ---Sub-Directory-2
 --------File1
 --------Sub-Directory-22019.zip

我尝试了嵌套的for循环,但似乎无法理解。我已经尝试过for命令,并且在集合(IN)中使用了skip和dir,但是无法使其正常工作。

我目前有以下脚本。

SET theYear=2019
For /D %%d in (*.*) do 7z a "%%d\%%d%theYear%.zip" ".\%%d\*"

除了我不知道如何排除每个文件夹中的最新文件(根据上次修改时间的最新文件)之外,这一切都完成了。

2 个答案:

答案 0 :(得分:1)

以下代码未经测试,因此执行时请小心:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "ROOT=Directory-Parent" & rem /* (set this to `%~dp0.` to specify the parent directory of the
                              rem     batch file, or to `.` to for current working directory) */
set "YEAR=2019"  & rem // (set the year just as a constant as it is unclear where to get it from)
set "MOVA="      & rem // (set this to `-sdel` if you want the files to be moved into the archive)

rem // Interate through the current working directory:
for /D %%d in ("%ROOT%\*.*") do (
    rem // Clear exclusion parameter for `7z`, reset flag that indicates if there are files left:
    set "EXCL=" & set "FLAG="
    rem /* Iterate through all files in the currently iterated directory, sorted from 
    rem    oldest to newest (`/O:D`), regarding the last modification date/time (`/T:W`);
    rem    the `findstr` part is to exclude the archive file itself if already present: */
    for /F "delims= eol=|" %%f in ('
        dir /B /A:-D /O:D /T:W "%%~d\*.*" ^| findstr /V /I /X /C:"%%~nxd%YEAR%.zip"
    ') do (
        rem // Exclusion parameter is not yet set in first loop iteration:
        if defined EXCL set "FLAG=#"
        rem // Exclusion parameter becomes set at this point:
        set "EXCL=-x!"%%f""
    )
    rem /* Flag is only set if there is one more file besides the one to exclude,
    rem    meaning that there are at least two files in total: */
    if defined FLAG (
        rem // Store folder information in variables to avoid loss of potentially occurring `!`:
        set "FOLDER=%%~fd" & set "NAME=%%~nxd"
        rem /* Toggle delayed expansion in order to be able to read variables that have been
        rem    set within the same block of parenthesised code (namely the `for` loops): */
        setlocal EnableDelayedExpansion
        rem // Execute the `7z` command line with dynamic parameters:
        ECHO 7z a -bd %MOVA% !EXCL! -x^^!"!NAME!%YEAR%.zip" "!FOLDER!\!NAME!%YEAR%.zip" "!FOLDER!\*.*"
        endlocal
    )
)

endlocal
exit /B

出于安全考虑,我在7z命令行之前(有潜在危险)ECHO

答案 1 :(得分:1)

此批处理文件可用于此任务:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginTop="36dp"
        android:ems="10"
        android:text="B"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginTop="36dp"
        android:gravity="center"
        android:text="A"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/editText"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

批处理文件从动态环境变量@echo off setlocal EnableExtensions DisableDelayedExpansion set "FilesToIgnore=1" set "theYear=%DATE:~-4%" set "ListFile=%Temp%\%~n0.lst" del "%ListFile%" 2>nul for /D %%I in (*) do call :CompressFiles "%%I" goto EndBatch :CompressFiles pushd %1 set "ZipFile=%~nx1%theYear%.zip" for /F "skip=%FilesToIgnore% eol=| delims=" %%J in ('dir /A-D /B /O-D /TW 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /X /C:"%ZipFile%"') do >>"%ListFile%" echo %%J if exist "%ListFile%" ( echo Compressing files in directory %1 ... 7z.exe a -bd -bso0 -i"@%ListFile%" -mx9 -scsDOS -- "%ZipFile%" del "%ListFile%" ) popd goto :EOF :EndBatch endlocal 的区域相关日期字符串动态设置环境变量theYear。请在命令提示符窗口DATE中执行,并验证输出是否为当前年份,因为echo %DATE:~-4%输出当前的本地日期,最后四个字符为年份。

批处理文件将忽略每个目录中的echo %DATE%个最新文件。如果该批处理文件的先前执行中已存在该ZIP文件,则也将被忽略。 ZIP文件从不包含在FilesToIgnore中,因为FilesToIgnore已经过滤掉了该文件,该文件过滤了命令findstr的输出,该命令输出的文件名没有上次修改时间排序的当前目录中的路径最先输出最新文件,最后输出最旧文件。

有关所使用的开关和参数,请阅读 7-Zip 的帮助。

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

  • dir
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • popd /?
  • pushd /?
  • set /?

阅读有关Using Command Redirection Operators的Microsoft文章,以获取setlocal /?2>nul的解释。重定向操作符|>必须用 FOR 命令行上的脱字符号|进行转义,以在Windows命令解释器处理此命令行时将其解释为原义字符。在执行命令 FOR 之前,该命令将在后台启动的单独命令进程中执行嵌入式命令行。

更新 7-Zip 版本19.00.0.0会输出警告,并使用如下所述的命令行在每个子目录中创建一个空的ZIP文件,该命令行最初用于批处理文件。我首先认为这是 7-Zip 版本19.00.0.0的错误,因为根据该版本的帮助和 7-Zip 版本,该版本也应支持^ 16.04.0.0可在命令行上使用:

--

必须从此命令行中删除7z.exe a -bd -bso0 -mx9 -scsDOS -- "%ZipFile%" "@%ListFile%" 才能使其与 7-Zip 19.00.0.0版一起使用。

因此,我reported this issue和7-Zip的作者迅速回答说,为什么使用--会导致搜索自 7起文件名中以--开头的文件-Zip 版本19.00.0.0:

  

我们需要某种方式从命令行添加@@file名称。
  因此,-file停止了--@的解析,并且7-Zip搜索了确切的名称。
  改为使用-更安全。

因此,我更新了批处理文件代码,并使用选项-i@listfile指定列表文件,这是指定列表文件的最安全方法。