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

Имейте в виду, что отрывки кодов и сценарий, приведенные в данной статье, могут удалять или перемещать папки или структуры каталогов. Прежде чем внедрять эти решения в производство, убедитесь, что они корректно работают в тестовых средах. В данной статье, я обозначал тела циклов команды For с помощью двух символов процента, аналогично тому, как они должны использоваться в сценариях (например, %%i, %%j). Если вы хотите запустить код непосредственно из командной строки, используйте одиночный знак процента (например, %i, %j).

В. Я хочу подсчитать количество пустых папок в файловой структуре. Я думал, что будет просто реализовать данную операцию с помощью сценария, но обнаружил, что оболочка написания сценариев, по-видимому, не обладает средством реализации теста Is Empty (пустая ли папка?). Существует ли простой способ решения моей проблемы?

О. Команда Rmdir позволяет вам удалять пустые папки, но вы не может проверить, является ли папка пустой, не попытавшись удалить ее. Однако если вы используете применительно к папке команду Dir и на выходе получаете пустую строку – очевидно, что папка пуста. Ниже приведен пример кода, который будет искать пустые папки в структуре каталогов и возвращать количество найденных папок:

Set folcntr=&For /F "tokens=*" 
%%i in ('Dir /AD /B /S
"R:sharedfolder"') Do
For /F "tokens=*" %%j in
('Dir /B "%%i" ^| Findstr $^
>NUL ^|^| Echo blah') Do Set
/A folcntr +=1

Принцип работы этого немного непонятного кода состоит в проверке выходных данных второй команды Dir ('Dir /B "%%i" ^| Findstr $^), то есть, содержат ли они имя файла или папки. Команда Findstr проверяет наличие в выходной строке «символа конца строки», обычно обозначаемого символом $. Если команда Findstr не смогла найти «символ конца строки», логический оператор OR (||) вызывает команду Echo для вывода на экран какого-либо сообщения. При запуске команды Echo, значение счетчика (переменная folcntr) увеличивается на 1. Имейте в виду, что все зарезервированные символы в теле команды For, должны писаться после префикса ^. Символ | является зарезервированным символом, поэтому для корректной работы встроенного оператора OR используется выражение ^|^|.

В. У нас очень большое сообщество пользователей с множеством общих папок. Я просмотрел некоторые из этих папок и обнаружил множество пустых каталогов New Folder. Каким образом эти папки появились в нашей структуре каталогов, и как проще всего избавиться от них, чтобы очистить структуру?

О. Несколько лет назад я выполнял похожее исследование и обнаружил несколько сотен папок New Folder в области общих ресурсов. Большинство из этих папок были пустыми. Видимо папки создаются, когда пользователи нажимают правую кнопку мыши и выбирают пункт New->Folder в контекстном меню. Когда в структуре каталогов создается новая папка, она часто перемещается в конец списка файлов и папок в окне Windows Explorer, и поэтому, пользователям трудно найти и переименовать ее. Пользователь не находит папку, и поэтому создает и переименовывает новую. «Потерянная» папка в дальнейшем не переименовывается и не используется до тех пор, пока ее, в конце концов, ни находят и ни удаляют. Проблема в том, что некоторые папки с именем New Folder могут действительно содержать данные, и, естественно, эти папки необходимо сохранить.

Если вам необходимо получить только список пустых папок New Folder, вы можете использовать технику применения команды Dir, описанную в предыдущем вопросе (тест Is Empty). Воспользуйтесь кодом:

Forfiles -p"R:sharedfolder" -s -m"*new folder*" 
-c"CMD /C If @ISDIR==TRUE Dir /B 0x22@PATH@FILE0x22
|Findstr $>NUL||Echo @PATH@FILE Is empty"

Для удаления папок используйте следующую команду:

Forfiles -p"R:sharedfolder" -s -m"*new folder*" 
-c"CMD /C If @ISDIR==TRUE Rmdir 0x22@PATH@FILE0x22
2>NUL&Echo @PATH@FILE"

Помните, что команда Forfiles работает только с локальными путями, а не с путями UNC. Если вам необходимо задать адрес файла с удаленного сервера, вы можете использовать логический сетевой диск. Также учтите, что в отличие от множества других встроенных команд и инструментов, между параметрами и переключателями команды Forfiles не должно быть пробелов. К примеру, в случае с переключателем пути -p"R:sharedfolder", обратите внимание на отсутствие пробела между символом «p» и открывающими двойными кавычками. Это относится ко всем переключателям команды Forfiles. Если вы добавляете пробел, выполнение команды Forfiles приведет к ошибке.

В. У нас среди общих ресурсов масса пустых папок. Требуется удалить их, но необходимо оставлять любые папки, созданные за последние 30 дней, на случай если пользователи создали папки или структуры каталогов, но еще не успели добавить данные. Я пытался использовать в связке команды Dir и Find, но оказалось, что при этом придется осуществлять независимый поиск файлов по каждой из дат. Как мне проще настроить удаление папок с ограничением по дате создания?

О. И в данном случае, наилучшим решением будет использование средства Forfiles. Используйте параметр date переключателя -d для распознавания старых папок. Воспользуйтесь кодом:

Forfiles -p"R:sharedfolder" -s -m*.* -d-30 
-c"CMD /C If @ISDIR==TRUE Rmdir 0x22@PATH@FILE0x22
2>NUL&Echo @PATH@FILE"

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

О. Я работал с множество прерванных проектов и сталкивался с такой же проблемой. Мне попадалась структура каталогов, содержащая сотни пустых папок. Проблема в том, что команда Rmdir не может удалить папки содержащие данные, поэтому, команда Rmdir, используемая в коде в предыдущем вопросе, будет удалять папки только на нижнем уровне структуры. Вам необходимо повторять исполнение кода, и при каждом проходе будет удаляться только один нижний уровень структуры. Однако при использовании команды Rmdir с переключателями /S и /Q, вы можете непреднамеренно удалить целиком структуру каталогов, содержащую какие-либо файлы. Поэтому, задача, которую вам необходимо решить, - безопасное удаление исключительно пустых папок начиная с нижнего уровня. Команда Dir (то есть, выражение Dir /S /AD /B "R:sharedfolder") предоставит вам список папок в формате по умолчанию «сверху-вниз». Команда Sort (^| Sort /R) изменяет порядок вывода результатов на противоположный для того, чтобы удаление папок с помощью команды Rmdir проходило в порядке «снизу-вверх». Приведенный ниже код использует команду Sort для удаления папок по схеме «снизу-вверх»:

For /F "Tokens=*" %%i in ('Dir /S /AD /B 
"R:sharedfolder" ^| Sort /R') Do Rmdir "%%i"

Если вас беспокоит, что вы можете удалить папки, которые недавно созданы, но еще не были заполнены файлами, используйте приведенную ниже команду Forfiles. Она осуществляет проверку, а потом позволяет удалять лишь те папки, с момента создания которых прошло более 60 дней:

For /F "Tokens=*" %%i in ('Forfiles -p"R: sharedfolder" -s -m*.* -d-60 -c"CMD /C If @ISDIR==TRUE 
Echo @PATH@FILE" ^| Sort /R') Do Rmdir "%%i"

В. Мне необходимо определить размер отдельных папок верхнего уровня структуры каталогов, а также их общий размер. Судя по-всему, решить проблему с помощью команды Dir будет сложно. Существует ли более простой способ?

О. Да, при использовании команды Dir придется выполнить множество операций фильтрования, чтобы получить желаемый результат. Правильней будет использовать средство DirUse, которое входит в состав пакетов Microsoft Windows Server 2003 Resource Kit, Windows XP Resource Kit и Windows 2000 Resource Kit. Это средство имеет много параметров, которые позволяют вам указать рабочую папку и размер папки. Для опроса папок верхнего уровня и поиска папок с размером более 25MB используйте базовый синтаксис, приведенный ниже:

DirUse /m /q:25 /* R:sharedfolder

где R:sharedfolder – ваша рабочая папка. Эта конструкция на выходе выдаст размер всех папок верхнего уровня и пометит восклицательным знаком все папки с размером более 25MB. Информацию об остальных параметрах ищите в файле помощи DirUse (DirUse /?).

В. Мы используем службу Robocopy для копирования области данных в новую область сервера. Мы сталкиваемся с массой неполадок, которые, по-видимому, связаны с проблемами длины пути. Как нам копировать данные, даже если их часть не укладывается в стандартное ограничение равное 256 символам?

О. Ранние версии службы Robocopy (1.95 и ниже) не поддерживают длинные пути. Версия XP010, входящие в наборы ресурсов систем Windows 2003 и XP, по умолчанию поддерживает копирование путей, длина которых больше 256 символов. Если вы хотите, чтобы служба Robocopy XP010 отказывалась работать с файлами и папками, превышающими этот предел, используйте переключатель /256, который не позволяет копировать эти файлы и папки. Также он будет прописывать ошибки в журнал операции. Если вы включили режим отказа, не забудьте про использование переключателей /R:1 (число повторных попыток) и /W:1 (количество секунд перед следующей попыткой). Если вы не понимаете, зачем вам может понадобиться режим отказа службы Robocopy, вспомните, что огромное количество приложений не может работать с файлами с длиной пути более 256 символов. Запуск команды Robocopy с переключателем /256 позволит вам обнаружить проблемные области и, возможно, заставит владельцев информации сократить пути, перед тем как вы начнете перемещение файлов.

Еще одной хитростью, которая может помочь вам при работе с длинными путями в ходе операции копирования, является назначение сетевых логических дисков на нижних уровнях структур каталогов в новой и старой областях данных. Вы можете использовать данную технику для сокращения эффективной длины пути. Когда вы копируете данные из папки ServerAShare1mydatamylongfilepathdata, вы используете 42 символа только для того, чтобы добраться до базовой папки, не обращаясь к подкаталогам и именам файлов. Если вы для данной папки назначите сетевой диск и используете логическое имя диска в коде службы Robocopy, вы сможете сократить путь на 40 символов.

В. У нас очень большая структура каталогов с массой редко используемых ссылок. Пользователи хотят, чтобы эти данные были доступны постоянно, но их хранение в основной структуре каталогов приведет к «захламленности». Какие архитектурные решения и ходы написания сценариев могут помочь выйти из данной ситуации?

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

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

Для создания области старых файлов, вам необходимо определить размер используемой области, в которую старые файлы будут перемещаться в ходе выполнения поиска на основе возраста файлов в вашей текущей общей области. Вы можете использовать службы Windows Search или Agent Ransack (доступна на сайте http://www.mythicsoft.com/agentransack) для поиска файлов, которые соответствуют указанным вами условиям. После того, как вы определите возрастной порог и информацию об объеме области, настройте сценарий ParallelRobo.bat и выполните тестовый запуск в режиме List. Ниже приведен синтаксис команды Robocopy в режиме перемещения файла /MOV:

"D:Robocopy.exe" "ServerNameSrcShare"
"ServerNameDestShare" /L /S /NP /TEE
/COPY:DATSOU /MOV /MINAGE:730 /R:1 /W:1
/LOG+:"D:Log.txt"

Я использовал следующие переключатели команды Robocopy в сценарии ParallelRobo.bat:

  • /S: Копирует НЕПУСТЫЕ подкаталоги.
  • /L: Только в режиме LIST. Это переключатель выдает список тех файлов, которые были бы перемещены в рабочем режиме. Файлы не копируются и не перемещаются.
  • /NP: Подавляет отображение хода выполнения операции.
  • /TEE: Отображает действия команды Robocopy в консоли, в то время как выходные данные по-прежнему перенаправляются в файл журнала операции.
  • /COPY:DATSOU: Вы можете использовать переключатель /COPY с настройками D (данные), A (атрибуты), T (временной штамп), S (разрешения NTFS), O (владелец), и U (аудит).
  • /MOV: Перемещает файлы, но сохраняет исходную структуру папок (отличается от переключателя /MOVE, который может удалять исходную структуру.)
  • /MINAGE:730: Задает минимальный возраст перемещаемых файлов. Значения может задаваться в количестве дней (например, 365, 730) или конкретной датой последнего изменения в формате YYYYMMDD (например, 20010121).
  • /R:1: Количество повторных попыток в случае сбоев при копировании или перемещении (при использовании сценария ParallelRobo.bat). Значение по умолчанию - 1000000!
  • /W:1: Количество секунд между повторными попытками. По умолчанию - 30 секунд.
  • /LOG+:"D:Log.txt": Прописывает результаты в файл журнала. Знак + указывает на то, что результаты будут добавляться в файл журнала, а не записываться вместо старых результатов.

Чтобы настроить сценарий ParallelRobo.bat для работы в вашем окружении, выполните следующие шаги:

  • Загрузите сценарий из данной статьи.
  • Укажите папку расположения службы Robocopy, папку из которой будут удалены файлы, а также другие элементы, которые необходимо задать в начале сценария. Указываемые пути не должны содержать "пробелов".
  • Протестируйте сценарий в режиме List (/L), запустив его без параметров. Тщательно изучите результаты в файле журнала перед тем как запускать сценарий в режиме перемещения файлов (/MOV). (Необходимо всегда тщательно тестировать свои сценарии перед их использованием в рабочем окружении.)
  • Перед запуском сценария в рабочем окружении убедитесь, что у вас имеется актуальная резервная копия области данных на случай, если потребуется восстановление данных.

Сценарий ParallelRobo.bat

:: Set RoboCopy Tool Location (Robocopy Version XP010 recommended)
Set RoboLoc=D:DataArchivingScriptsRobocopy.exe

:: Set Source Location
Set SrcLoc=ServerNameSrcShare

:: Set Destination Location
Set DestLoc=ServerNameDestShare

:: Set Log Dir Location
Set LogLocDir=D:DataArchivingScripts

:: Set Days Threshold for File Moves
:: This can be expressed in two ways:
:: the number of days (365, 730, etc) or a date in the past (YYYYMMDD or 20010121)
Set DaysThr=730

If /I "%1"=="move" Goto :MoveFiles
Goto :ListFiles

:MoveFiles
Echo Moving files based on %DaysThr% day threshold from "%SrcLoc%" to "%DestLoc%"
"%RoboLoc%" "%SrcLoc%" "%DestLoc%" /S /NP /TEE /COPY:DATSOU /MOV /MINAGE:%DaysThr%
 /R:1 /W:1 /LOG+:"%LogLocDir%MovedLog.txt"

Goto :EOF

:ListFiles

Echo List only mode invoked - no files will be moved
Echo To run this script and actually perform file moves, use syntax: ParallelRobo.bat move
Echo List results based on %DaysThr% day threshold from "%SrcLoc%" to "%DestLoc%"
"%RoboLoc%" "%SrcLoc%" "%DestLoc%" /L /S /NP /TEE /COPY:DATSOU /MOV /MINAGE:%DaysThr%
 /R:1 /W:1 /LOG+:"%LogLocDir%ListLog.txt"

Goto :EOF