List all files and dirs without recursion with junctions
This was somehow a hard question. Even StackOverflow has only fancy solutions.
But here is a simple one for listing all files recursively without junction folder loops.
Use PowerShell and test each file if it contains the attribute "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
- Paste the code into a text file and save it as PowerShell (.ps1) script
- Place the script inside your desired folder to list all files+folder recursively
- Execute the script with PowerShell. A new file called
outputlist.txt
at the same location will appear
Quick comparison between the Powershell script and a common batch command
powershell - good, no indefinite loops
batch "DIR /B /S" - bad, indefinite loops through junctions points
Using powershell more succinctly:
$items = @(pwd);
while($items){ $newitems = $items | Get-ChildItem | Where-Object -Property Attributes -NotLike *ReparsePoint*; $newitems; $items = $newitems | Where-Object -Property Attributes -Like *Directory* }
To get this all into a text file, just surround the whole thing with parenthesis and pipe it into out-file.
( $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. Use small script, so everything will be listed, but junctions won't be followed.
Works fine on Windows 7, unlike option below in this answer
let's call it dnj.cmd
(like in 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
)
First FOR/DIR for output, second FOR/DIR for recursion. This way, you can also adjust output parameters (specifically, DIR and ECHO arguments). For example, if you only want flat list of files in output without directories, use
FOR /F "usebackq delims=" %%F IN (`DIR %1 /B /A-D`) DO ECHO %%~F
in place of first FOR.
Invoking: dnj.cmd
path [path [...]]
Output redirection works same way as with conventional DIR, so
cmd /C "dnj.cmd "%USERPROFILE%" | CLIP"
works from Win+R ("Run") prompt.
2. If you're on Windows 10, use DIR /S /A-L
This way, junctions won't be listed, neither will be recurred with /S. On Windows 7, DIR /S /AD-L recurses junctions. Not sure about 8/8.1.
batch with output to text file:
CHCP 65001 & REM for UTF-8
DIR %* /B /S /A-L > out.txt
(pass path and additional DIR args as batch arguments)
cmd.exe to clipboard (can be invoked via Win+R):
cmd /C "CHCP 65001 & DIR "%USERPROFILE%" /B /S /A-L | CLIP"
Clipboard is unicode by default, but without CHCP beforehand, DIR output is in OEM codepage, so some characters may be lost.
Quotes after /C are required by CMD syntax, despite it looks weird with inner quotes around %USERPROFILE%
.