3

Существует ли собственный | портативный инструмент, который может дать мне Unicode (или, по крайней мере, системно-совместимый) список всех файлов и каталогов по пути рекурсивно, без повторения точек соединения или ссылок в Windows?

Например, встроенная команда dir , а также takeown и icacls запускаются в бесконечный цикл с каталогом Application Data (1).

РЕДАКТИРОВАТЬ Я хотел бы иметь возможность получить текстовый файл или, по крайней мере, легко перенести буфер обмена в качестве вывода.

10 ответов10

5

Это был как-то сложный вопрос. Даже у 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 
  1. Вставьте код в текстовый файл и сохраните его как скрипт PowerShell (.ps1).
  2. Поместите скрипт в нужную папку, чтобы вывести список всех файлов + папок рекурсивно
  3. Выполните скрипт с помощью PowerShell. В этом же месте появится новый файл с именем outputlist.txt

Быстрое сравнение между скриптом Powershell и обычной пакетной командой

powershell  - good, no indefinite loops

batch "DIR /B /S" - bad, indefinite loops through junctions points

2

Использование 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
1

Проблема здесь в том, что кто-то удалил антирекурсию из папки Application Data.

Он должен иметь DENY для ВСЕГО, чтобы перечислить папку / чтение данных.

Если вы хотите войти в него, используйте папку AppData, на которую он указывает.

Существует две точки соединения - одна в %userprofile% и другая в %userprofile%\local .

0

Эта проблема может быть связана с удалением антирекурсных разрешений из папки «Данные приложения» (например, может применяться к любой точке соединения 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")}

0

Из приглашения CMD:

dir /A:-L /S /B

РЕДАКТИРОВАТЬ: Хотя это не будет перечислять фактическое соединение в каталоге, в котором он находится, он будет повторять вниз по соединению.

0

1. Используйте небольшой скрипт, чтобы все было в списке, но переходы не будут выполняться.

Хорошо работает на Windows 7, в отличие от варианта ниже в этом ответе

давайте назовем это dnj.cmd (как в Dir No Junctions)

@(SETLOCAL ENABLEEXTENSIONS
ECHO OFF

CHCP 65001>NUL
IF "%~1"=="" (CALL :listDir .) ELSE CALL :listDir %1
EXIT /B
)
:listDir <path>
( FOR /F "usebackq delims=" %%F IN (`DIR %1 /B /A`) DO ECHO %~1\%%~F
FOR /F "usebackq delims=" %%F IN (`DIR %1 /B /AD-L`) DO CALL :listDir "%~1\%%~F"
EXIT /B )

Первый FOR/DIR для вывода, второй FOR/DIR для рекурсии. Таким образом, вы также можете настроить выходные параметры (в частности, аргументы DIR и ECHO). Например, если вам нужен только плоский список файлов на выходе без каталогов, используйте

( FOR /F "usebackq delims=" %%F IN (`DIR %1 /B /A-D`) DO ECHO %%~F

вместо первого ЗА.

Вызов: dnj.cmd 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% .

0

Оригинальная символическая ссылка для Application Data имеет специальные разрешения и атрибуты для предотвращения Everyone из чтения или просмотра содержимого целевой папки ( с помощью символической ссылки). Это предотвращает попадание программ в рекурсивный цикл. Вы можете легко повторно применить разрешения и атрибуты, но будьте очень осторожны, чтобы применять эти разрешения и атрибуты только к символической ссылке, а не к любым действительным файлам или папкам. Символическая ссылка будет значком в проводнике Windows со стрелкой быстрого доступа над значком папки.

  1. Откройте проводник Windows
  2. Нажмите клавишу « alt и нажмите « Сервис», затем « Параметры», затем перейдите на вкладку « Вид ».
  3. Отключите параметр [ ] Hide protected operating system files и включите параметр (x) Show hidden files, folders, or drives .
  4. Перейдите к C:\Users\[user]\AppData\Local
  5. Щелкните правой кнопкой мыши символьную ссылку « Application Data и выберите « Свойства» (убедитесь, что это символическая ссылка, а не настоящая папка - она должна иметь стрелку быстрого доступа в виде наложения поверх значка папки)
  6. Перейдите на вкладку « Безопасность », затем « Дополнительно», затем « Изменить разрешения».
  7. Добавить « Everyone и установить права для Everyone :
    • Применить к = только эта папка (<-это важно)
    • Разрешения = запретить папку / чтение данных (<- это останавливает рекурсию)
  8. Нажмите кнопку ОК, а затем нажмите кнопку Да, чтобы предупредить, что правило « Запретить» применяется перед правилом « Разрешить».
  9. Нажмите OK еще раз, чтобы применить изменения
  10. Перейдите на вкладку « Владелец », нажмите « Изменить», затем нажмите « Другие пользователи или группы».
  11. Введите 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 до их первоначальных значений, чтобы не видеть файлы, которые должны быть скрыты.

0

Это может быть не нативный инструмент, но он может быть полезен для кого-то с 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 - это другая история.

0

В 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 для фильтрации файлов на основе расширенных атрибутов

0

В PowerShell

Get-ChildItem /Recurse <path> |
Where-Object { $_.Mode -notlike 'd*l' } |
ForEach-Object { $_.FullName};

Вы можете просто передать вывод в файл, если хотите сохранить его.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .