Скопируйте папку первого уровня и объедините все файлы в подпапках - PullRequest
0 голосов
/ 01 октября 2019

У меня есть несколько папок s1, s2 ..... sn в главном каталоге. Каждая из этих папок имеет несколько вложенных папок, папок в папках, а затем файлы. Структура вида выглядит так:

mainDir

  -s1
       -f1
         -c1
           -a.txt
           -b.txt
         -c2
           -m.txt
           -n.txt
       -f2
         -c1
           -aaa.txt
           -bbb.txt
         -c2
           -mmm.txt
           -nnn.txt
     -s2
       -f1
         -c1
           -a.txt
           -b.txt
         -c2
           -m.txt
           -n.txt
       -f2
         -c1
           -aaa.txt
           -bbb.txt
         -c2
           -mmm.txt
           -nnn.txt
     -s3 ..................

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

DestDirectory
      -s1
        -a.txt
        -b.txt
        -m.txt
        -n.txt
        -aaa.txt
        -bbb.txt
        .....so on
      -s2
        -a.txt
        -b.txt
        -m.txt
        -n.txt
        -aaa.txt
        -bbb.txt
        .....so on

Ответы [ 3 ]

1 голос
/ 01 октября 2019

Я бы использовал for /D цикл для итерации подкаталогов первого уровня, а затем вложенный for /R цикл для итерации всех файлов в непосредственном подкаталоге. каталогов, затем используйте copy, чтобы скопировать каждый файл по отдельности, чтобы получить плоскую целевую иерархию каталогов. Чтобы избежать конфликтов имен файлов (это означает, что файлы с одним и тем же именем появляются на разных уровнях иерархии подкаталогов источника), можно использовать директиву if exist. Итак, вот код:

rem // Loop through immediate sub-sirectories of main directory:
for /D %%I in ("D:\MainDir\*") do (
    rem // Temporarily change to the currently iterated sub-directory:
    pushd "%%~I" && (
        rem // Iterate through all files in the current directory recusrively:
        for /R %%J in ("*.*") do (
            rem /* Create destination directory if necessary, which is named like
            rem    the current directory, that is the first source sub-directory: */
            2> nul md "D:\CopyDir\%%~nxI"
            rem // Temporarily change to the destination directory:
            pushd "D:\CopyDir\%%~nxI" && (
                rem // Check for potential file name collisions:
                if not exist "%%~nxJ" (
                    rem // No collision, hence copy current file:
                    copy "%%~J" "%%~nxJ"
                ) else (
                    rem // Collision, so return an error message:
                    >&2 echo ERROR: "%%~nxI\%%~nxJ" already exists!
                )
                rem // Return from destination directory:
                popd
            )
        )
        rem // Return from currently iterated source sub-directory:
        popd
    )
)
0 голосов
/ 02 октября 2019

Чем это отличается от вашего предыдущего вопроса? Как скопировать файлы из подпапки только с помощью cmd?

Возможно, в вашем предыдущем вопросе у вас были все папки с одинаковыми именами?

Приведенный ниже код также должен работать дляпапки с разными именами, как вы описали здесь.

CMD Script:

@(SETLOCAL
  ECHO OFF
  SET "_MainDir=C:\Main\Dir"
  SET "_DestDir=%Temp%\Destination\Main\Dir"
)

FOR /D %%A in (
  %_MainDir%\*
) DO (
  IF NOT EXIST "%_DestDir%\%%~nxA" MD "%_DestDir%\%%~nxA"
  FOR /F %%a IN ('
    DIR /A-D /S /B "%%~fA\*"
  ') DO (
    ECHO Copying: "%%~fa"
    ECHO To: "%_DestDir%\%%~nxA\%%~nxa"
    COPY /B /V /Y "%%~fa" "%_DestDir%\%%~nxA\%%~nxa"
  )
)
0 голосов
/ 01 октября 2019

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

=== Find-DupeFilenames.ps1

$h = @{}

Get-ChildItem -File -Recurse |
    ForEach-Object {
        if ($h.ContainsKey($_.Name)) {
            "Name conflict {0} is in both {1} and {2}" -f @($_.Name, $h[$_.Name], $_.DirectoryName)
        } else {
            $h.Add($_.Name, $_.DirectoryName)
        }
    }

Если вам нужно запустить это из командной строки cmd.exe, используйте это для быстрого подсчета.

CD /D C:\mainDir
powershell -NoLogo -NoProfile -Command "(C:\src\Find-DupeFilenames.ps1 | Measure-Object).Count"

Используйте это, чтобы получить список всех конфликтующих имен файлов.

CD /D C:\mainDir
powershell -NoLogo -NoProfile -Command ".\Find-DupeFilenames.bat"
...