batch-filevariablestextplaylistedt

Batch file to delete absolute paths and leave only filename in multiple files


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.


Solution

  • @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 name and eXtension 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 - echoing %result% would have echoed 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 thenechowith an argument that is resolved to *nothing* reportsecho 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.