196

I have the following batch script from Wikipedia:

@echo off
    for /R "C:\Users\Admin\Ordner" %%f in (*.flv) do (
    echo %%f
)
pause

In the for-loop all files with the extension flv get echoed, but I want the make some actions with the file(s) where I need one time the file without the extension and one time with the extension. How could I get these two?

I searched for solutions but I don't find one. I'm a real newbie in batch...

Poru
  • 8,254
  • 22
  • 65
  • 89

7 Answers7

380

You can use %%~nf to get the filename only as described in the reference for for:

@echo off
    for /R "C:\Users\Admin\Ordner" %%f in (*.flv) do (
    echo %%~nf
)
pause

The following options are available:

Variable with modifier  Description

%~I                     Expands %I which removes any surrounding 
                        quotation marks ("").
%~fI                    Expands %I to a fully qualified path name.
%~dI                    Expands %I to a drive letter only.
%~pI                    Expands %I to a path only.
%~nI                    Expands %I to a file name only.
%~xI                    Expands %I to a file extension only.
%~sI                    Expands path to contain short names only.
%~aI                    Expands %I to the file attributes of file.
%~tI                    Expands %I to the date and time of file.
%~zI                    Expands %I to the size of file.
%~$PATH:I               Searches the directories listed in the PATH environment 
                        variable and expands %I to the fully qualified name of 
                        the first one found. If the environment variable name is 
                        not defined or the file is not found by the search,
                        this modifier expands to the empty string.    
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • 16
    Just a quick note: in the above example **%%f** would be something like `C:\Users\Admin\Ordner\foo.flv` and **%%~nf** would give you `foo`. If you want everything _except_ the extension use **%%~df%%~pf%%~nf** which would give you `C:\Users\Admin\Ordner\foo` – ehambright Aug 02 '17 at 22:05
  • 16
    @ehambright Late comment, but I guess using `%%~dpnf` would be a shorter alternative. –  Mar 28 '18 at 12:07
  • 1
    Thanks for the modifier/ description table Dirk. My case was getting the file name without extension from param `%1` in a batch script. `echo %~n1` was what I was after. – Dave Pile Nov 30 '19 at 09:13
39

In case the file your variable holds doesn't actually exist the FOR approach won't work. One trick you could use, if you know the length of the extension, is taking a substring:

%var:~0,-4%

the -4 means that the last 4 digits (presumably .ext) will be truncated.

Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
  • 1
    This is not working for me (on Win8.1) -- maybe I misunderstand it when trying `echo %f:~0,-4%` in the context of the example used in the question. What am I doing wrong? – Wolf Nov 23 '15 at 14:24
  • 3
    Apparently that works for "normal" variables, not FOR variables (or maybe I just don't know the correct syntax). Anyway this will work in the context of the OP example: `SET fl=%%f` and then `echo %fl:~0,-4%` – Ohad Schneider Nov 23 '15 at 14:46
  • @Wolf you need to set value of the loop variable to a normal variable then do string substitution/truncation in the normal variable – phuclv Nov 30 '16 at 16:47
  • In more than enough cases, the extension length does not equal 3 or is unknown. You can still use a for even if the file does not exist, see my answer. – marsze Feb 17 '20 at 08:17
15

Without looping

I am using this if I simply want to strip the extension from a filename or variable (without listing any directories or existing files):

for %%f in ("%filename%") do set filename=%%~nf

If you want to strip the extension from a full path, use %%dpnf instead:

for %%f in ("%path%") do set path=%%~dpnf

Example:

(Use directly in the console)

@for %f in ("file name.dat") do @echo %~nf
@for %f in ("C:\Dir\file.dat") do @echo %~dpnf

OUTPUT:

file name
C:\Dir\file
marsze
  • 15,079
  • 5
  • 45
  • 61
14

I'm also a stranger to windows cmd, but try this:

echo %%~nf
Vineet
  • 2,103
  • 14
  • 9
9

This is a really late response, but I came up with this to solve a particular problem I had with DiskInternals LinuxReader appending '.efs_ntfs' to files that it saved to non-NTFS (FAT32) directories :

@echo off
REM %1 is the directory to recurse through and %2 is the file extension to remove
for /R "%1" %%f in (*.%2) do (
    REM Path (sans drive) is given by %%~pf ; drive is given by %%~df
    REM file name (sans ext) is given by %%~nf ; to 'rename' files, move them
    copy "%%~df%%~pf%%~nf.%2" "%%~df%%~pf%%~nf"
    echo "%%~df%%~pf%%~nf.%2" copied to "%%~df%%~pf%%~nf"
echo.
)
pause
Agi Hammerthief
  • 2,114
  • 1
  • 22
  • 38
  • I'm not sure it answers the asked question, but it actually helped me, thanks! – matan7890 Aug 06 '14 at 23:42
  • 1
    @matan7890 True; the op doesn't specify what "I want the make some actions with the file(s)" [sic] entails, but one of those actions may be renaming them, in which case my answer is an expansion of the accepted answer. – Agi Hammerthief Aug 07 '14 at 06:29
  • This helped a friend of mine who opened an attachment and had `.encrypted` added to all his files, along with a ransom demand. Apparently the attacking script must have been a batch file that is the reverse of this and added `.encrypted` to all files. – AwokeKnowing Mar 22 '16 at 19:13
  • 1
    upvoted because you mention the drive, path, and extension (**%%~df%%~pf%%~nf**) which most closely resembles the output of **%%f** from the orginal question, instead of *just* the filename without extension (**%%~nf**) – ehambright Aug 02 '17 at 22:10
9

If your variable is an argument, you can simply use %~dpn (for paths) or %~n (for names only) followed by the argument number, so you don't have to worry for varying extension lengths.

For instance %~dpn0 will return the path of the batch file without its extension, %~dpn1 will be %1 without extension, etc.

Whereas %~n0 will return the name of the batch file without its extension, %~n1 will be %1 without path and extension, etc.

The full thing is %~dpfn0 and it starts to make sense, when you take a closer look:

  • d is drive
  • p is path
  • n is name
  • x is extension, and
  • fn is filename with extension
Martin Braun
  • 10,906
  • 9
  • 64
  • 105
  • Thank you! `%~dpn` kept the whole file path except the extension as wanted, while `%~nf` kept the extension somehow. – Guillaume F. Apr 28 '21 at 16:05
  • @GuillaumeF. yes, thanks for pointing that out. I updated my answer to give a little bit more insight into the letters. – Martin Braun Apr 28 '21 at 23:28
  • **f** is **f**ilename, **x** is e**x**tension – Mud Dec 11 '21 at 19:03
  • +1 for the meaning of these letters. I dislike batch (but use anyway), so I usually copy/paste these without giving much thought to these letters. Now, I know :) – akinuri Feb 23 '23 at 11:45
1

Using cygwin bash to do the chopping

  :: e.g. FILE=basename.mp4 => FILE_NO_EXT=basename
  set FILE=%1
  for /f "delims=" %%a in ('bash -c "FILE=%FILE%; echo ${FILE/.*/}" ') do set FILE_NO_EXT=%%a
mosh
  • 1,402
  • 15
  • 16