Список всех файлов и директорий без рекурсии с переходами
Существует ли собственный | портативный инструмент, который может дать мне Unicode (или, по крайней мере, системно-совместимый) список всех файлов и каталогов по пути рекурсивно, без повторения точек соединения или ссылок в Windows?
Например, встроенный dir
команда, а также takeown
а также icacls
запустить в бесконечный цикл с каталогом данных приложения ( 1).
РЕДАКТИРОВАТЬ Я хотел бы иметь возможность получить текстовый файл или, по крайней мере, легко перенести буфер обмена в качестве вывода.
10 ответов
Это был как-то сложный вопрос. Даже у StackOverflow есть только модные решения.
Но вот простой способ для рекурсивного перечисления всех файлов без зацикливания папки соединений.
Используйте PowerShell и протестируйте каждый файл, если он содержит атрибут "ReparsePoint"
function Recurse($path) {
$fc = new-object -com scripting.filesystemobject
$folder = $fc.getfolder($path)
foreach ($i in $folder.files) { $i | select Path }
foreach ($i in $folder.subfolders) {
$i | select Path
if ( (get-item $i.path).Attributes.ToString().Contains("ReparsePoint") -eq $false) {
Recurse($i.path)
}
}
}
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$outputlist = Recurse($scriptPath) | Out-File -Filepath .\outputlist.txt
- Вставьте код в текстовый файл и сохраните его как скрипт PowerShell (.ps1).
- Поместите скрипт в нужную папку, чтобы вывести список всех файлов + папок рекурсивно
- Выполните скрипт с помощью PowerShell. Новый файл называется
outputlist.txt
в том же месте появится
Быстрое сравнение между скриптом Powershell и обычной пакетной командой
powershell - good, no indefinite loops
batch "DIR /B /S" - bad, indefinite loops through junctions points
Оригинальная символическая ссылка для Application Data
имеет специальные разрешения и атрибуты для предотвращения Everyone
от чтения или просмотра содержимого целевой папки (по символической ссылке). Это предотвращает попадание программ в рекурсивный цикл. Вы можете легко повторно применить разрешения и атрибуты, но будьте очень осторожны, чтобы применять эти разрешения и атрибуты только к символической ссылке, а не к любым действительным файлам или папкам. Символическая ссылка будет значком в проводнике Windows со стрелкой быстрого доступа над значком папки.
- Откройте проводник Windows
- Нажмите
alt
и нажмите Инструменты, затем Параметры, затем перейдите на вкладку Вид - Отключить опцию
[ ] Hide protected operating system files
и включите опцию(x) Show hidden files, folders, or drives
, - Перейдите к
C:\Users\[user]\AppData\Local
- Щелкните правой кнопкой мыши
Application Data
символическая ссылка и выберите " Свойства" (убедитесь, что это символическая ссылка, а не настоящая папка - она должна иметь стрелку быстрого доступа в виде наложения поверх значка папки) - Перейдите на вкладку " Безопасность ", затем " Дополнительно", затем " Изменить разрешения".
- добавлять
Everyone
и установить права наEveryone
чтобы:- Применить к = только эта папка (<-это важно)
- Разрешения = запретить папку / чтение данных (<- это останавливает рекурсию)
- Нажмите кнопку ОК, а затем нажмите кнопку Да, чтобы предупредить, что правило " Запретить" применяется перед правилом " Разрешить".
- Нажмите OK еще раз, чтобы применить изменения
- Перейдите на вкладку " Владелец ", нажмите " Изменить", затем нажмите " Другие пользователи или группы".
- Тип
SYSTEM
и продолжайте нажимать кнопку ОК, пока не вернетесь в проводник Windows
Рекурсия теперь отключена. Есть еще одна вещь, которую вы можете захотеть сделать. Большинство этих типов символических ссылок имеют специальные атрибуты файлов, чтобы они не были видны пользователям. Откройте командную строку и выполните следующие команды:
cd "%userprofile%\AppData\Local"
attrib +S +H +I /L "Application Data"
/L
вариант говорит attrib
применять +S +H +I
на символическую ссылку, вместо применения ее к целевой папке (C:\Users\[user]\AppData\Local
).
Если вы запутались, вы можете легко удалить символическую ссылку и воссоздать ее из командной строки. Будьте осторожны, чтобы создать заново, чтобы он указывал на ту же папку, что и раньше. dir /a
Команда покажет вам, где Application Data
указывает на. Вам следует дословно набрать целевую папку как последний параметр mklink
команда.
cd "%userprofile%\AppData\Local"
attrib -H -S -I /L "Application Data"
dir /a
rd "Application Data"
mklink /J "%userprofile%\AppData\Local\Application Data" "%userprofile%\AppData\Local"
Теперь у вас есть Application Data
символическая ссылка, которая имеет проблему рекурсии. Так что просто следуйте инструкциям выше, чтобы исправить проблему рекурсии.
Не забудьте изменить настройки на шаге 3 до их первоначальных значений, чтобы не видеть файлы, которые должны быть скрыты.
1. Используйте небольшой скрипт, чтобы все было в списке, но переходы не будут выполняться.
Хорошо работает на Windows 7, в отличие от варианта ниже в этом ответе
давай называть это dnj.cmd
(как в Dir No Junctions)
@(ECHO OFF
SETLOCAL ENABLEEXTENSIONS
CHCP 65001>NUL
IF "%~1"=="" (CALL :listDir .) ELSE CALL :listDir %*
EXIT /B
)
:listDir <path>
FOR /F "usebackq delims=" %%F IN (`DIR /B /A "%~1"`) DO ECHO %~1\%%~F
(
IF EXIST "%~1\*.*" FOR /F "usebackq delims=" %%F IN (`DIR /B /AD-L "%~1"`) DO CALL :listDir "%~1\%%~F"
IF "%~2"=="" EXIT /B
SHIFT
GOTO :listDir
)
Первый FOR/DIR для вывода, второй FOR/DIR для рекурсии. Таким образом, вы также можете настроить выходные параметры (в частности, аргументы DIR и ECHO). Например, если вам нужен только плоский список файлов на выходе без каталогов, используйте
FOR /F "usebackq delims=" %%F IN (`DIR %1 /B /A-D`) DO ECHO %%~F
вместо первого ЗА.
Вызов: dnj.cmd
path [path [...]]
Перенаправление вывода работает так же, как и с обычным DIR, поэтому
cmd /C "dnj.cmd "%USERPROFILE%" | CLIP"
работает из командной строки Win+R ("Выполнить").
2. Если вы используете Windows 10, используйте DIR /S /AL
Таким образом, соединения не будут перечислены, и не будут повторяться с /S.В Windows 7 DIR /S /AD-L повторяет соединения.Не уверен насчет 8/8.1.
пакет с выводом в текстовый файл:
CHCP 65001 & REM for UTF-8
DIR %* /B /S /A-L > out.txt
(передать путь и дополнительные аргументы DIR в качестве пакетных аргументов)
cmd.exe в буфер обмена (может быть вызван через Win+R):
cmd /C "CHCP 65001 & DIR "%USERPROFILE%" /B /S /A-L | CLIP"
Буфер обмена по умолчанию является юникодом, но без CHCP заранее вывод DIR находится в кодовой странице OEM, поэтому некоторые символы могут быть потеряны. Кавычки после /C требуются синтаксисом CMD, несмотря на то, что это выглядит странно с внутренними кавычками %USERPROFILE%
,
Использование powershell более лаконично:
$items = @(pwd);
while($items){ $newitems = $items | Get-ChildItem | Where-Object -Property Attributes -NotLike *ReparsePoint*; $newitems; $items = $newitems | Where-Object -Property Attributes -Like *Directory* }
Чтобы поместить все это в текстовый файл, просто заключите все это в круглые скобки и передайте его во внешний файл.
( $items = @(pwd); while($items){ $newitems = $items | gci | where -Property Attributes -NotLike *ReparsePoint*; $newitems; $items = $newitems | where -Property Attributes -Like *Directory* } ) out-file myfile.txt
Это может быть не нативный инструмент, но он может быть полезен для кого-то с Windows 7, есть программа под названием FileLocator Pro, у которой есть опция в Advanced/Junction Points, чтобы отключить поиск точек соединения.
Как только это будет сделано, вы можете использовать программу командной строки flpsearch следующим образом:
"C:\Program Files\Mythicsoft\FileLocator Pro\flpsearch.exe" -o c:\biglist.txt -d c:\;d:\;e:\ -ofbs -f *
Echo Started cleanup
for /F "tokens=1-2 delims= " %%i in (c:\biglist.txt) do if "!prevx!" neq "%%i" (ECHO %%i >> c:\big.txt & (if /i "%%j" neq "on" echo %%j >> c:\big.txt) & set prevx=%%i) else (if /i "%%j" neq "on" echo %%j >> c:\big.txt)
Там есть буквальные вкладки после эхо и разделителей, поэтому убедитесь, что ваш текстовый редактор не преобразовывает вкладки в пробелы.
Надеюсь, что это может быть полезно для пользователя Win7 или двух.
Конечно, опции PowerShell тоже хороши, но пакет DOS - это другая история.
Проблема здесь в том, что кто-то удалил антирекурсию из папки Application Data.
Он должен иметь DENY для ВСЕГО, чтобы перечислить папку / чтение данных.
Если вы хотите войти в него, используйте папку AppData, куда он указывает.
Есть две точки соединения - одна в %userprofile%
и еще один в %userprofile%\local
,
Из приглашения CMD:
dir / A: -L / S / B
РЕДАКТИРОВАТЬ: Хотя это не будет перечислять фактическое соединение в каталоге, в котором он находится, он будет повторять вниз по соединению.
Эта проблема может быть связана с удалением антирекурсных разрешений из папки "Данные приложения" (например, может применяться к любой точке соединения Windows Vista+, созданной для обратной совместимости).
Эти точки соединения должны иметь разрешения DENY to EVERYONE в списке папок / чтения данных, которые будут иметь приоритет над любыми разрешениями ALLOW, и, надеюсь, не будут обойдены никакими программами рекурсии каталога из-за способа доступа к файловой системе.
Из https://msdn.microsoft.com/en-us/library/windows/desktop/bb968829(v=vs.85).aspx может показаться, что точки соединения определяются по наличию ReparsePoint
атрибут, наряду с Hidden
а также System
атрибутов.
Следующая команда Powershell является основой того, что кажется более простым решением для исключения точек соединения из рекурсий каталога, чем любой предыдущий ответ.
get-childitem $RootDirectoryForRecusion -recurse -force | where-object {-not ($_.Attributes -match "ReparsePoint" -and $_.Attributes -match "Hidden" -and $_.Attributes -match "System")}
В PowerShell 3.0 появился новый параметр Attribute:
Перечисляет структуру каталогов без соединительных папок:
Get-ChildItem -Path $RootDirectory -Attributes !ReparsePoint -Recurse -Force -ErrorAction SilentlyContinue
Перечисляет папки соединений только из структуры каталогов:
Get-ChildItem -Path $RootDirectory -Attributes ReparsePoint -Recurse -Force -ErrorAction SilentlyContinue
Дополнительная информация: использование PowerShell 3.0 для фильтрации файлов на основе расширенных атрибутов
В PowerShell
Get-ChildItem /Recurse <path> |
Where-Object { $_.Mode -notlike 'd*l' } |
ForEach-Object { $_.FullName};
Вы можете просто передать вывод в файл, если хотите сохранить его.