I'm in over my head here. I'm trying to write a .bat file that will go through every line in multiple .m3u playlist files to delete the path and leave only the filename.
Example input:
C:\Users\username\Music\Dr. Dre\Dr. Dre & Snoop Doggy Dog - Ain't Nothin But A G-Thang.mp3
C:\Users\username\Music\Ed Sheeran\x (Deluxe Edition)\04 Don't.mp3
C:\Users\username\Music\Eric Church\Chief (2011)\06-eric_church-homeboy.mp3
Desired output:
Dr. Dre & Snoop Doggy Dog - Ain't Nothin But A G-Thang.mp3
x (Deluxe Edition)\04 Don't.mp3
06-eric_church-homeboy.mp3
I have searched high and low with no luck getting the desired output. I also don't have enough experience to make this easy. In my multiple failed attempts, this is what I have come up with so far:
@echo off
setlocal enableDelayedExpansion
for /f "tokens=* delims= eol=~" %%G in ('dir /b "C:\Users\username\Documents\Playlists\*.m3u"') do (
SET Remove=*
SET Result=%Remove:*\=% )
ECHO %Result%
The approach I'm trying to use is to take each line and delete everything prior to, and including, the \
symbol. So far, I've been able to get the script to reach its end without an error but it's not actually doing anything.
Any help would be greatly appreciated. Thank you in advance.
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
for /f "delims=" %%G in ('dir /b /a-d "%sourcedir%\*.m3u"') do (
REM "%%G" contains the name+extension of each M3U file in turn
for /F "usebackq delims=" %%q in ("%sourcedir%\%%G") do (
rem %%q contains the entire contents of the file "%%G" - each such line is itself a full-filename
for /f "delims=" %%s in ("%%q") do echo %%~nxs
)
)>"%destdir%\%%~nxG"
GOTO :EOF
You would need to change the settings of sourcedir
and destdir
to suit your circumstances. The listing uses a setting that suits my system.
In the first line, the dir/b
output is assigned to the metavariable %%G
. The /a-d
switch turns OFF directorynames, should a directory name fitting *.m3u
be encountered.
"delims="
assigns the line of dir
output to %%G
- the whole line, and nothing but the line. These lines are the names of the files encountered on scanning the directory.
Note the structure for ... do ( ....whatever.... )>"filename"
. This means gather any output from ( ....whatever.... )
into a new file. (>>
in place of >
would append to an existing file, or create a new file if there is no existing file...) named using the n
ame and eX
tension of %%G
. If you wanted .txt
output files instead of .M3u
(matching the extension in %%G
) then you'd simply use %%~nG.txt
.
Now we process each of the files "%%G
". Since the name may include spaces, so the usebackq
option needs to be used. Again, delims=
will assign the entire line read from the file to %%q
.
So %%q
is a filename. Process this using for/f
as a literal (by "quoting"
it) and we can then use %%~nxs
to "display" the "name and extension" of %%s
.
So - what went wrong with your version?
Well, tokens=*
and delims=
essentially do the same thing (but the former suppresses leading-delimiters like spaces). eol=~
would have truncated any filename-output from dir
before the ~
, which may not have actually occurred - it's just a lurking problem.
Within the loop, you are setting remove
. Two small problems here. First, better to use the syntax SET "var=value"
(where value may be empty; in which case var
becomes undefined) is used to ensure that any stray trailing spaces are NOT included in the value assigned.
Second, and more seriously, when you use Remove
in the next line, the value of Remove
as it stood when the for
was encountered would be used since your code uses %Remove...%
. To use the current value as you expect, you need to turn on delayedexpansion
(as you have) and use !Remove...!
. Even there, you'd have attempted to assign the processed-value to result
.
Using set "remove=%%G"
would have been a little better (not what you want, as %%G
is the name of the .m3u
file - not its content, but better) and then you'd try to set result
to the contents of "remove" with all leading characters up to and including the first "\" replaced by *nothing*
So, had the content of the variable being processed been for example C:\Users\username\Music\Ed Sheeran\x (Deluxe Edition)\04 Don't.mp3
as you apparently anticipated, then the result would have been simply to remove the C:\
.
And then - echo
ing %result%
would have echo
ed nothing since result
had no value when the for
was encountered. echo !result!
may have worked a little better (!
because the value has been modified by the loop)but then
echowith an argument that is resolved to *nothing* reports
echo is off` (or on, as the case may be), not an empty line as might be expected.
Complicated, innit? Nevermind - batch is fun once you get the hang of it.