3

I'm trying to list all the files which have extra suffix after the extension E.g: .txt.1 or .txt.2 etc..

I'm using txt. but it's giving all the file names instead of only the files with extra suffix

for %%A in (*txt.*) do (call :renum "%%A")

after this I'm writing my program to rename the files accordingly. Can someone please check and help.

Bharath
  • 45
  • 5
  • The pattern should read `*.txt.*` (note the added dot)... – aschipfl Jul 12 '16 at 14:19
  • @aschipfl: have you tried what happens when you do that? – zb226 Jul 12 '16 at 14:24
  • tried that already, but it didn't work – Bharath Jul 12 '16 at 14:24
  • @zb226, no I haven't, but it's obvious that `*txt.*` matches something like `file.txtxtxt.1` but `*.txt.*` doesn't; besides that, there is no more difference, both will match `file.txt.1.2` (unintentionally)... – aschipfl Jul 12 '16 at 14:36
  • 1
    If you know precise character limitations, then you could perhaps use ? instead of *, which may help a little. However, you may still need to run an additional if check inside your for loop, like zb226' answer. – ManoDestra Jul 12 '16 at 15:24

3 Answers3

2

One solution would be to filter by extension inside the loop:

FOR %%A IN (*txt.*) DO (
    IF NOT "%%~xA"==".txt" CALL :renum "%%A"
)

This works by using the "enhanced substitution of FOR variable references", in this case %%~xA. You can get an overview of all the available substitutions by executing FOR /?.

Update:

  • This solution does not work case-insensitively, because that was neither explicitly demanded or prohibited. Use IF /I instead of plain IF if case-insensivity is desired.
  • As dbenham notes, there are edge cases:
    • name.txt.txt will not be processed. If that's OK is not clearly stated, but rather likely.
    • name_txt.ext will be processed, which is due to the given wildcard *txt.* and can be avoided by using *.txt.* instead. My rationale to not change it in the first place was that only the OP knows his actual set of files, and I assumed he had a reason for choosing it (a situation common in these types of questions).
Community
  • 1
  • 1
zb226
  • 9,586
  • 6
  • 49
  • 79
1

You could use two nested for loops like this:

rem // Corrected file pattern (added a `.`):
for %%A in ("*.txt.*") do (
    rem // Check (last) file extension:
    if /I not "%%~xA"==".txt" (
        rem // Remove (last) file extension:
        for %%B in ("%%~nA") do (
            rem // Check next-to-last file ext.:
            if /I "%%~xB"==".txt" (
                call :renum "%%~A"
            )
        )
    )
)

According to the help of for (type for /? in a command prompt window), the ~x modifier of the for variable retrieves the file extension (which is the last dot . and everything after). The ~n modifier retrieves all but the file extension, hence the file (base) name. The code above uses two nested for loops to get the last and the next-to-last file extensions and checking them against .txt (in a case-insensitive manner).

Note that the call command line is not executed for files ending in .txt.txt.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • +1, But I don't understand why you included your first IF statement that filters out names like "name.txt.txt". I suppose that might be desired in some circumstances, but I would probably want to rename names like that. – dbenham Jul 12 '16 at 18:13
  • @dbenham, because of the OP's example where the extra suffix is numeric like `.1`, `.2`,... I assumed if the last extension is `.txt`, it is already fine... – aschipfl Jul 12 '16 at 20:58
1

I would use FINDSTR with DIR /B and FOR /F

The following will process names with any number of extra extensions like name.txt.ext and name.txt.ext.ext, etc. This includes a name like name.txt.txt

for /f "delims= eol=:" %%F in (
  'dir /b /a-d *.txt.*^|findstr /i "\.txt\."'
) do call :renum "%%F"

This variation will only process names with a single extra extension like name.txt.ext (including name.txt.txt)

for /f "delims= eol=:" %%F in (
  'dir /b /a-d *.txt.*^|findstr /i "\.txt\.[^.]*$"'
) do call :renum "%%F"

You might also check into my JREN.BAT regular expression file renaming utility. It can probably filter and rename all your files in one step, without any need for a custom batch script.

For example, the following will only rename files looking like "name.txt.ext", and transform them into "name_ext.txt"

jren "(\.txt)\.([^.]+)$" "_$2$1" /i
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • What if the file name has txt in it? – Bharath Jul 13 '16 at 08:18
  • @Bharath - The leading dot literal in the search string prevents matching txt within the base name. Technically speaking, `.txt` would be considered part of the base name if it is not at the end, but we are assuming that is the intended extension. – dbenham Jul 13 '16 at 10:15
  • 1
    @Bharath - If you want to include a name like `XXXXtxt.ext`, without the leading dot. then simply use `'dir /b /a-d *txt.*^|findstr /i "txt\."'` – dbenham Jul 13 '16 at 10:20