endigo
endigo

Reputation: 69

DOS CMD batch: Wrong full pathnames? (parameter extension ~f)

To list full pathnames of files in specified path I may use:

FOR /F "tokens=*" %G IN ('DIR /B "path\*.*"') DO echo %~fG

WRONG result: <current_directory>\*.*

ss64.com says: "If a filename with no drive letter/path is expanded to display a drive letter/path the command shell will assume; often incorrectly; that the file resides in the current directory."

This is quite a silly behaviour. However this is probably the problem as DIR here returns a bare filename.

IS THERE ANY WAY TO AVOID SUCH MISTAKE? As it is very easy to make.

I know I can use /S option in DIR command, which makes the result be a full pathname but it also goes through subfolders which is undesired.

Using following syntax everything goes fine but I can't use the advantages of DIR command:

FOR %G IN ("path\*.*") DO echo %~fG

result: <path>\*.*

Do you have any tips or tricks how to work with DIR and full paths?

Upvotes: 2

Views: 517

Answers (3)

Mofi
Mofi

Reputation: 49186

The environment variable CD contains at any time the path of current directory always without backslash at the end.

So you can use for your example:

@echo off
set "DirectoryPath=%CD%\path"
for /F "tokens=*" %%G in ('dir /B "path\*.*"') do echo %DirectoryPath%\%%G

Therefore whenever using DIR with bare output format without using also /S, it is necessary to determine first the directory path and reference this path within body of FOR loop.

Example on using fixed absolute paths:

@echo off
for /F "tokens=*" %%G in ('dir /B "C:\Temp\My Folder\*.*"') do echo C:\Temp\My Folder\%%G

Don't forget the double quotes with path or file name containing a space on other commands than echo!

Upvotes: 1

Dmitry Sokolov
Dmitry Sokolov

Reputation: 3190

If you really need to use the dir command

@echo off
setlocal ENABLEDELAYEDEXPANSION

set _subdir=path
set _mask=*.*

call :get_absolute_path _prefix "%CD%\%_subdir%"

rem  Iterate through a list of files, including files in subdirectories
for /f "tokens=*" %%A in ('dir /b /s /a:-d "%_prefix%\%_mask%"') do (
    rem  The current full file path
    set _f=%%A
    rem  Cut the "%CD%\%_subdir%\" prefix from the current file path
    set _f=!_f:%_prefix%\=!
    rem  Test whether the relative file path has a "subdir\" prefix:
    rem    split the relative file path by "\" delimiter and
    rem    pass %%B and %%C tokens (subdir and the remainder) to the loop
    for /f "delims=\ tokens=1*" %%B in ("!_f!") do (
        rem  If the remainder is empty string then print the full file path
        if "%%C"=="" echo %%A
    )
)

endlocal
exit /b 0

:get_absolute_path
set %1=%~f2
exit /b 0

Upvotes: 0

MichaelS
MichaelS

Reputation: 6042

How about using FORFILES? This will give you the full path for any desired folder:

forfiles /p C:\Some\Directory\ /c "cmd /c echo @path"

FORFILES is really mighty as it povides lots of options such as filters, rucursion into subfolders, etc. For more info check this website.

Upvotes: 0

Related Questions