Check if the path is File or Folder using batch [duplicate] - windows

This question already has answers here:
How to test if a path is a file or directory in Windows batch file?
(6 answers)
Closed 1 year ago.
I am trying to check if the path defined in the program is file or a folder using batch file. Everything is working fine but when I try to give a path that isn't file or folder or doesn't have permission to access it, it gives output saying "it is a File".
Here is the code.
#ECHO off
SETLOCAL ENABLEEXTENSIONS
set ATTR=D:\Download\Documents\New
dir /AD "%ATTR%" 2>&1 | findstr /C:"Not Found">NUL:&&(goto IsFile)||(goto IsDir)
:IsFile
echo %ATTR% is a file
goto done
:IsDir
echo %ATTR% is a directory
goto done
:done

I would suggest the following method:
#Echo Off
Set "ATTR=D:\Download\Documents\New"
For %%Z In ("%ATTR%") Do If "%%~aZ" GEq "d" (Echo Directory
) Else If "%%~aZ" GEq "-" (Echo File) Else Echo Inaccessible
Pause

Your problem is a logical one: you check, if it's a folder, but you don't check, if it's a file, so you have either "folder" or "not a folder". You need another check for "file". But finding "Not Found" makes it language dependent, which generally should be avoided. Here is a language independent solution:
for does list all attibutes (there is a Direcotry attribute), which even attrib doesn't.
#echo off
break>Existing.File
md ExistingFolder
set "attr=Existing.File"
REM set "attr=ExistingFolder"
REM set "attr=does not exist"
for /f %%x in ("%attr%") do set attrib=%%~ax/
set "attrib=%attrib:~0,1%"
if "%attrib%"=="d" echo %attr% is a directory
if "%attrib%"=="-" echo %attr% is a file
if "%attrib%"=="/" echo %attr% does not exist
Note: this method even detects a folder, where you don't have access to (but does not detect such files)

Related

Recursively change file extensions to lower case

I have a game that I play and mod a lot, and a lot of the files in the game have file extensions that are in all caps, which bothers me quite a bit. I'm trying to change them all to be lowercase, but there are numerous folders in the game files, so I'm having to be very repetitive. Right now, I'm working with this:
cd\program files (x86)\Activision\X-Men Legends 2\Actors
start ren *.IGB *.igb
cd\program files (x86)\Activision\X-Men Legends 2\Conversations\
start ren *.XMLB *.xmlb
cd\program files (x86)\Activision\X-Men Legends 2\Conversations\act0\tutorial\tutorial1
start ren *.XMLB *.xmlb
and so on for each and every folder in the game files. I have a very long .bat file where I just have line after line of this but with a different destination folder. Is there a way to streamline this process so I don't have to manually type out each folder name? Also, is there a line that I could add at the beginning to automatically run as an administrator, so I don't have to make sure to run the .bat file as an administrator each time?
I'm not looking for anything complicated, and I'm very inexperienced with coding other than the small amount of stuff I've been able to search up.
Instead of doing it for each folder, use a for /R loop which loops through all subfolders. I would suggest the following code:
#echo off
:prompt
set /p "extensions=What are the up-case extensions you want to convert to lower-case?: "
if not defined extensions (cls & goto:prompt) else (goto:loop)
:loop
for %%A IN (%extensions%) do (
for /R "custom_folder" %%B IN (*.%%A) do (
ren "%%~fB" "%%~nB.%%A"
)
)
Take a look on this on how to run this batch file as admin. Create another batch file and add the code specified in the accepted answer.
Note: As Stephan pointed out in the comments, you can use %ProgramFiles(x86)% environment variable which is the same thing.
#echo off
setlocal
rem Check if admin.
2>nul >nul net session || goto :runasadmin
rem Start in script directory.
pushd "%~dp0" || (
>&2 echo Failed to change directory to "%~dp0".
pause
exit /b 1
)
rem Ask for directory to change to, else use the script directory if undefined.
set "dirpath=%~dp0"
set /p "dirpath=Dir path: "
rem Expand any environmental variables used in input.
call set "dirpath=%dirpath%"
rem Start in the input directory.
pushd "%dirpath%" || (
>&2 echo Failed to change directory to "%dirpath%".
pause
exit /b 1
)
rem Ask for file extensions.
echo File extensions to convert to lowercase, input lowercase.
echo i.e. doc txt
set "fileext="
set /p "fileext=File extension(s): "
if not defined fileext (
>&2 echo Failed to input file extension.
pause
exit /b 1
)
rem Display current settings.
echo dirpath: %dirpath%
echo fileext: %fileext%
pause
rem Do recursive renaming.
for %%A in (%fileext%) do for /r %%B in (*.%%A) do ren "%%~B" "%%~nB.%%A"
rem Restore to previous working directory.
popd
echo Task done.
pause
exit /b 0
:runasadmin
rem Make temporary random directory.
set "tmpdir=%temp%\%random%"
mkdir "%tmpdir%" || (
>&2 echo Failed to create temporary directory.
exit /b 1
)
rem Make VBS file to run cmd.exe as admin.
(
echo Set UAC = CreateObject^("Shell.Application"^)
echo UAC.ShellExecute "cmd.exe", "/c ""%~f0""", "", "runas", 1
) > "%tmpdir%\getadmin.vbs"
"%tmpdir%\getadmin.vbs"
rem Remove temporary random directory.
rd /s /q "%tmpdir%"
exit /b
This script is expected to start from double-click.
It will restart the script as admin if not already admin.
It will prompt to get information such as directory to change to and get file extensions i.e. doc txt (not *.doc *.txt). If you enter i.e. %cd% as the directory input, it will be expanded.

Moving files with spaces in name batch scripting

So I'm trying to mimic some features of Apple
One feature I am currently working on is being able to select a single or multiple files then through the "context menu" creating a "new folder" (directed to a batch file passing along file through FOR loop) then moving the files into that "new folder"
The issue I am having is with file names with spaces I researched using "robocopy" but finding it tricky alittle tricky
My code so far
#echo off
set cDir=%~dp1
set newFolder="%cDir%NewFolder"
md %newFolder%
echo.
:: get each selected file and echo
for %%I in (%*) do (
echo %%I
echo.
echo %newFolder%
move "%%I" "%newFolder%"
echo.
)
pause
Your modified code should move files and folders as well. To be on the safe side, here is my variant of your code. Note quotation changes in set, md and move statements but I repeat: your (modified) variant of quotation should work as well:
#echo off
set cDir=%~dp1
set "newFolder=%cDir%NewFolder"
md "%newFolder%"
echo.
:: get each selected file and echo
for %%I in (%*) do (
echo %%I
echo.
echo %newFolder%
move "%%~I" "%newFolder%\"
echo.
)
pause
Although move /? says Moves files and renames files and directories, both Source and Target may be either a folder or a single file (resource, verified on my Win-8).
Proof.
==>move "D:\Path\COCL\bu bu bu" "D:\Path\content\"
1 dir(s) moved.
==>move "D:\Path\content\bu bu bu" "D:\Path\COCL\"
1 dir(s) moved.
==>
Next resource: Command Line arguments (Parameters).

How to get attributes of a file using batch file

I am trying to make a batch file to delete malicious files from pendrive. I know that these malicious files uses hidden,read only and system attributes mainly to hide itself from users. Currently i am deleting these files using cmd by removing malicious files attributes then deleting it. Now I am thinking to make a small batch file which can be used to remove these files just by entering the drive letter.
I have found this code in a website to find attributes of a file. But after entering the name of the file the batch file just exits without showing any results.
#echo off
setlocal enabledelayedexpansion
color 0a
title Find Attributes in Files
:start
set /p atname=Name of the file:
if not exist %atname% (
cls
echo No file of that name exists!
echo.
echo Press any key to go back
pause>nul
goto start
)
for /f %%i in (%atname%) do set attribs=%%~ai
set attrib1=!attribs:~0,1!
set attrib2=!attribs:~1,1!
set attrib3=!attribs:~2,1!
set attrib4=!attribs:~3,1!
set attrib5=!attribs:~4,1!
set attrib6=!attribs:~5,1!
set attrib7=!attribs:~6,1!
set attrib8=!attribs:~7,1!
set attrib9=!attribs:~8,1!
cls
if %attrib1% equ d echo Directory
if %attrib2% equ r echo Read Only
if %attrib3% equ a echo Archived
if %attrib4% equ h echo Hidden
if %attrib5% equ s echo System File
if %attrib6% equ c echo Compressed File
if %attrib7% equ o echo Offline File
if %attrib8% equ t echo Temporary File
if %attrib9% equ l echo Reparse point
echo.
echo.
echo Press any key to go back
pause>nul
goto start
can you tell me why this batch file is exiting without showing any results. Or can you give any better batch script for getting attributes of a file.
EDIT
I was able to work the above code only for a single file. As my purpose of my batch file is to remove malicious files by entering the drive letter. How can i use it to find what kind of attributes files are using in a particular drive.
For example:
In cmd we can use this command to find the file attributes of a given drive
attrib *.*
Advance thanks for your help
I tried the bat file (without inspecting the details) and it seems to work fine for me. What I noticed is that it closes instantly if you don't enclose file path with quotation marks - e.g. "file". Example:
Name of the file: path\file.txt // this will close immediately
Name of the file: "path\file.txt" // now it will stay open and display the result
This hopefully solves your problem.
As far as your question in EDIT is concerned, a simple option is to iterate a list of files and execute the batch on each one.
batch1.bat: (%1 refers to the first command-line parameter)
#echo off
setlocal enabledelayedexpansion
echo %1
set atname=%1
for %%i in ("%atname%") do set attribs=%%~ai
set attrib1=!attribs:~0,1!
set attrib2=!attribs:~1,1!
set attrib3=!attribs:~2,1!
set attrib4=!attribs:~3,1!
set attrib5=!attribs:~4,1!
set attrib6=!attribs:~5,1!
set attrib7=!attribs:~6,1!
set attrib8=!attribs:~7,1!
set attrib9=!attribs:~8,1!
cls
if %attrib1% equ d echo Directory
if %attrib2% equ r echo Read Only
if %attrib3% equ a echo Archived
if %attrib4% equ h echo Hidden
if %attrib5% equ s echo System File
if %attrib6% equ c echo Compressed File
if %attrib7% equ o echo Offline File
if %attrib8% equ t echo Temporary File
if %attrib9% equ l echo Reparse point
echo.
echo.
Next, generate a list of all files within a given path (say 'folder' including all subfolders):
dir /s /b folder > ListOfFiles.txt
main.bat (read ListOfFiles.txt line-by-line and pass each line to batch1.bat as a command line parameter):
#echo off
for /f "tokens=*" %%l in (ListOfFiles.txt) do (batch1.bat %%l)
Then, from cmd:
main.bat >> output.txt
The last step generates an output file with complete results. Granted, this can be done in a more polished (and probably shorter) way, but that's one obvious direction you could take.
You're using a for /f loop here, which isn't necessary (and may yield undesired results if the filename contains spaces). Change this:
for /f %%i in (%atname%) do set attribs=%%~ai
into this:
for %%i in ("%atname%") do set attribs=%%~ai
This is dangerous code - but it'll delete read only, hidden and system files.
It should fail to run on c: drive but I haven't tested it. Note that some Windows installs are on drives other than c:
#echo off
echo "%cd%"|find /i "c:\" >nul || (
del *.??? /ar /s /f
del *.??? /ah /s
del *.??? /as /s
)

How to test if a path is a file or directory in Windows batch file?

I searched here, found someone using this
set is_dir=0
for %%i in ("%~1") do if exist "%%~si"\nul set is_dir=1
but didn't work, when %1==c:\this is a file with spaces.csproj, the test still success, which means it will still be treated as a folder!!!
anyone knows the answer, i guess this is a very common problem and Windows has existed for many many years, it should have a very simple solution....
I know the if exist path\nul test for a folder used to work on MS-DOS. I don't know if it was broken with the introduction of long file names.
I knew that if exist "long path\nul" does not work on Windows batch. I did not realize until today that if exist path\nul works on Vista and beyond as long as path is in the short 8.3 form.
The original code appears to work on Vista. It seems like it should work on XP as well, but I believe the following XP bug is getting in the way: Batch parameter %~s1 gives incorrect 8.3 short name.
The original code does not need the FOR loop, it could simply use %~s1
Here is a variation that fully classifies a path as INVALID, FILE or FOLDER. It works on Vista, but does NOT work on XP because of the %~s1 bug. I'm not sure how it performs on MS-DOS.
EDIT 2015-12-08: There are a number of Windows situations where this fails
#echo off
if not exist "%~1" ( set "type=INVALID" ) else if exist %~s1\nul ( set "type=FOLDER" ) else ( set "type=FILE" )
#echo "%~1" = %type%
I believe this variation will work with nearly all versions of Microsoft batch, including MS-DOS and XP. (it obviously won't work on early versions of DOS that don't support PUSHD)
#echo off
if exist "%~1" (2>nul pushd "%~1" && (popd&set "type=FOLDER") || set "type=FILE" ) else set "type=INVALID"
echo "%~1" = %type%
UPDATE 2014-12-26
I'm pretty sure the following will work on all versions of Windows from XP onward, but I have only tested on Win 7.
Edit 2015-12-08: This can fail on network drives because the folder test can falsely report a file as a folder
#echo off
if exist %1\ (
echo %1 is a folder
) else if exist %1 (
echo %1 is a file
) else (
echo %1 does not exist
)
UPDATE 2015-12-08
Finally - a test that truly should work on any Windows version from XP onward, including with network drives and UNC paths
for /f "tokens=1,2 delims=d" %%A in ("-%~a1") do if "%%B" neq "" (
echo %1 is a folder
) else if "%%A" neq "-" (
echo %1 is a file
) else (
echo %1 does not exist
)
Note - This technique is intended to be used for a path without any wildcards (a single specific file or folder). If the provided path includes one or more wildcards, then it provides the result for the first file or folder that the file system encounters. Identical directory structures may give different sort order results depending on the underlying file system (FAT32, NTFS, etc.)
I just tried in this way. Hope this helps.
#ECHO OFF
SET CURR_DIR=%CD%
SET IS_DIR=0
CD %1%
IF "%ERRORLEVEL%"=="0" SET IS_DIR=1
CD %CURR_DIR%
ECHO IS DIRECTORY %IS_DIR%
Output:
D:\Work\Stand alone Java classes>test.bat D:\Work\Training
IS DIRECTORY 1
D:\Work\Stand alone Java classes>test.bat D:\Work\Training\SRT.txt
The directory name is invalid.
IS DIRECTORY 0
The /ad option for "dir" command lists folders, /b option for bare. Assuming you have checks for the existence of file in place, use:
dir /ad /b ChangeThisToYourFilename 1> NUL 2> NUL
if %ERRORLEVEL% EQU 0 (
echo is a file
) else (
echo is NOT a file
)
For a 1 liner:
dir /a:d /b C:\Windows 2>&1 | findstr /i /n /c:"File Not Found">nul && (#echo. Im a file) || (#echo. Im a folder)
e.g. change C:\Windows to C:\Windows\Notepad.exe
-Sorry Arun, dbenham, didn't read yours! Same as..
Previously, I used the "\nul" method, but for a long time now, I have used "\*" to test if an existing filespec is a folder or a file. As far as I know, it works on all versions of Windows, from Windows 95 (and perhaps earlier versions) through all current Windows versions.
So, as with other methods, first test if the file exists. Then, to see if it's a "Folder", test it with: if exist "%fspec%\*":
if not exist "%fspec%" goto :NotExistOrInvalid
rem "%fspec%" is "Valid" and is either a "Folder", or a "File".
if exist "%fspec%\*" goto :IsValidAndIsAFolder
rem "%fspec%" is a "File" (a "Regular File" or a Shortcut/Link).
goto :IsValidAndIsAFile
For example:
set "fspec=XYZ:%perlpath%"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem Invalid, goto :NotExistOrInvalid
set "fspec=%perlpath%"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem goto :NotExistOrInvalid
rem "%fspec%" Is a "Valid" filespec and is either a "Folder", or a "File".
if exist "%fspec%\*" (echo "%fspec%" is a "Folder".) else echo "%fspec%" is a "File".
set "fspec=%perlpath%\perl.exe"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem Invalid, goto :NotExistOrInvalid
rem "%fspec%" Is a "Valid" filespec and is either a "Folder", or a "File".
if exist "%fspec%\*" (echo "%fspec%" is a "Folder".) else echo "%fspec%" is a "File".
The output for this is:
"XYZ:F:\usr\perl\bin": Invalid or not found
"F:\usr\perl\bin" is a "Folder".
"F:\usr\perl\bin\perl.exe" is a "File".
This solution combines the file attribute parameter extension (%~a1) with variable substring extraction (%variable:~0,1%):
#ECHO OFF
CALL :is_directory C:\Windows
CALL :is_directory C:\MinGW\share\doc\mingw-get\README
CALL :is_directory C:\$Recycle.Bin
CALL :is_directory "C:\Documents and Settings"
CALL :is_directory "%LOGONSERVER%\C$\Users\All Users"
GOTO :EOF
:is_directory
SETLOCAL
SET file_attribute=%~a1
IF "%file_attribute:~0,1%"=="d" (
ECHO %file_attribute% %1 is a directory
) ELSE (
ECHO %file_attribute% %1 is NOT a directory
)
ENDLOCAL
GOTO :EOF
Output:
d-------- C:\Windows is a directory
--a------ C:\MinGW\share\doc\mingw-get\README is NOT a directory
d--hs---- C:\$Recycle.Bin is a directory
d--hs---l "C:\Documents and Settings" is a directory
d--hs---l "\\MYCOMPUTER\C$\Users\All Users" is a directory

Check for existence of all files before building a project

How would one go best about checking for existence of all files before building?
Let me explain; I mostly build stuff from the command prompt. No problems there, just put the build command and all in one .bat /.cmd file, and run it. It works fine.
But, for the normal running of my program, for example, I need several source files for the build, and then an additional few data files, measured data and such.
Is there a way to test via a batch file whether a file exists, and if it exists just write OK?
file1.for OK
file2.for OK
datafile.txt OK
data.dat MISSING FROM DIRECTORY
How could this be accomplished?
As a slightly more advanced approach:
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set FileList=file1.for file2.for "File with spaces" ...
Set Build=1
For %%f In (%FileList%) Do Call :FileExists %%f
If Not Defined Build (
Echo.
Echo Build aborted. Files were missing.
GoTo :EOF
)
...
GoTo :EOF
:FileExists
Set FileName=%~1
If Exist "!FileName!" (
Echo !FileName! OK
) Else (
Echo !FileName! MISSING FROM DIRECTORY
Set Build=
)
GoTo :EOF
You can put all files into the FileList variable. The Build variable controls whether to continue with the build. A single missing file causes it to cancel.
Something like this?
#ECHO OFF
IF EXIST "c:\myfile1.txt" (ECHO myfile1.txt OK) ELSE (ECHO myfile1.txt FILE MISSING FROM DIRECTORY)
IF EXIST "c:\myfile2.txt" (ECHO myfile2.txt OK) ELSE (ECHO myfile2.txt FILE MISSING FROM DIRECTORY)
For a list of available commands, see http://ss64.com/nt/

Resources