topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Thursday March 28, 2024, 4:50 am
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Last post Author Topic: remv: Rename files (and directories) with regular expressions  (Read 37545 times)

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
The fan of old-school tools strikes again.  8)
(NANY 2019, anyone?)

Do you know what's missing in both POSIX and Windows? Right: A sane way to rename files/directories with a regular expression.
The usual approach on POSIX systems is:

ls * | sed -E 's/(.*)text(.*)to(.*)remove(.*)/mv & "$1$2$3$4"/' | sh

That is horrendously ugly and does not port well to Windows. Here is my slightly less horrendously ugly attempt to fix that:
https://code.rosaelefanten.org/remv

Enjoy.
« Last Edit: June 01, 2022, 09:27 AM by Tuxman »

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #1 on: January 07, 2019, 10:46 AM »
Nice idea, and certainly can be useful.

After a quick test on Win10, there are some problems:
  • When providing an invalid input pattern, but trying to provide an option parameter, the shown error text quotes the parameter as the input regex (e.g. "remv -n [a $1" returns error message "remv could not parse your input regex: -n")
  • Running valid regex without any options does nothing, running with -n (simulate) just writes some empty lines to console, running with -v (verbose) actually renames while also indeed being verbose. I haven't checked other options yet.
  • For replacement pattern $0 isn't valid, and treated as a literal (e.g. "remv -v .* pre$0" will rename file1.ext to "pre$0" instead of "prefile1.ext", and then will error that it can't rename "otherfile.ext" because "pre$0" already exists). Of course there's the workaround of explicitly putting the matching pattern in parenthesis, but it shouldn't be required and something like $0 should work for the entire pattern.
  • When renaming files in current directory (I didn't test any folder/directory/move handling so far) the verbose display (which as mentioned for now seems a must) lists each file as starting with ".\" before the name. That's... technically correct (the files are in the current folder), but not really expected (or helpful) when renaming files locally without any indication from the user that the location should be managed.  Worse, the ".\" at the beginning of the file name also matches the input regex. So doing something like "remv -v (.*?)(\..*$) $1 $2" fails for trying to rename the folder, to "a.\" (instead of trying to add a space before the first period in the file name) which results in an appropriate "operation not permitted"
  • This one is more of a feature request than a problem, but for file-name handling it's a very common/basic feature (and also partially related to the previous item): It should be possible to treat the file extension separately, with something like an optional parameter to specify whether it should/shouldn't be considered as a part of the regex. Otherwise this will just require a heck of a lot of "(.*)(\..*$)", or somesuch, in matching pattern and replacement group when wanting to rename files without modifying the extension

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #2 on: January 07, 2019, 10:56 AM »
1. Yes, thank you.
2.  :huh: I'll check that.
3. If you use invalid variables, that's not my fault.  :D
4. The possibility to include relative folder paths (to move whole structures) is actually a feature. How would you do that?
5. File extensions are technically not a separate part of a file name. Handling files with multiple endings (.tar.gz) could be tricky...

Note that I'll have to fix the Decision Sieve first anyway, so take the above comments as temporary ideas.  ;D

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #3 on: January 07, 2019, 11:54 AM »
Perfectly understandable. And thanks for the quick response.  :)

And of course what I present here are just my opinions, as much as I personally may think they're valid and correct one.

3. If the regex engine you're using doesn't support something like this, then of course not much you can do. But generally most (all?) user tools for search&replace that I can quickly think of (and regex code/development libraries) allow something like a "fake" backreference to the full match. Usually (in my experience) that's done by something like $0 or \0 (e.g. a capturing group for everything before the first actual capturing group) for tools that otherwise use $n or \n , . It's mostly a convenience thing, so not strictly necessary, but it's a very common one ("why do I explicitly need to indicate the group boundaries when this group is already very clearly defined, and is already a known individual entity to the engine?"). Though, again, yes, if it's not something that your regex engine handles, then it's technically correct, so this does downgrades to feature-request rather than bug.

4. Oh, I like that as a feature, for sure. But I think it should be done only if the user explicitly wants to use it, otherwise it should just be assumed.
If the user didn't explicitly provide the location, then it shouldn't match anything on the input regex. If working on "file.ext" in the current directory then it's called "file.ext", not ".\file.ext". If the user wants to move it somewhere then they don't replace .\(.*) with c:\somewhere\$1 , but rather (.*) with c:\somewhere\$1 . This should carry fine to sub-folders of the current folder.
If not using the current folder (or using sub-folders in the pattern) then the user needs to specify the path explicitly anyway, so no problems there. The ".\" should be a valid destination location (I didn't check if it is now), but shouldn't be matching on the input unless explicitly put there by the user.

5. Since it's posted here as a windows tool, file extensions are very much a separate part of a file name, both for the O/S and for the expectations of the very large majority of users. Files with ".tar.gz" are handled by programs that know how to open ".gz" files, which hopefully also know to notice that the base name ends with ".tar" and what it means (which for practical purposes I think anything that handles ".gz" is aware of). But as far as the O/S is concerned, when making file associations/icons/filters, that file has a ".gz" extension. And file renaming can often includes the desire to change the file name without touching the extension.

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #4 on: January 07, 2019, 02:25 PM »
To come back to 3.: I use the standard C++ regex header. Technically, $0 is supposed to work.  :huh:

1. is fixed (I removed the reference).  ;D
2. Head -> wall.
4. is actually already in, just skip the -r flag and remv will gladly ignore directories.
5. is fixed as well (new flag "-E").

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #5 on: January 07, 2019, 03:51 PM »
I checked the new version.

Regarding 4, that's not it. Even without the -r flag, the ".\" is still considered a part of the file name.

Example: Trying to clean file names (replace various separators, including decimal dots, with spaces) with a few files in the local directory:
c:\tmp\test>remv -Evv "[-+._]" " "
 Processing '.\bla.txt'.
 Renaming     '.\bla.txt' to ' \bla.txt' ... error: operation not permitted
 Processing '.\file.with.dots.txt'.
 Renaming     '.\file.with.dots.txt' to ' \file with dots.txt' ... error: operation not permitted
 [STATS] Renamed 0 files (2 failed, 0 skipped).

expected: "bla.txt" left as-is since it doesn't match, "file.with.dots.txt" changed to "file with dots.txt" . But the ".\" at the start doesn't let this happen.

Example: adding a prefix to any file (behavior is the same if the "(.*)" is replaced with something to filter, it just of course happens with the relevant/matching files  ) :
C:\tmp\test>remv -Evv (.*) "prefix-$1"
 Processing '.\bla.txt'.
 Renaming     '.\bla.txt' to 'prefix-.\bla.txt' ... error: operation not permitted
 Processing '.\file.with.dots.txt'.
 Renaming     '.\file.with.dots.txt' to 'prefix-.\file.with.dots.txt' ... error: operation not permitted
 [STATS] Renamed 0 files (2 failed, 0 skipped).

expected: file "bla.txt" will be renamed to "prefix-bla.txt", same with the other.



There's also another issue here (which would have interfered with the above even without modifying the ".\" ). It seems that it fails to rename anything when -E is used. It uses it correctly in what it shows as the expected file name, but fails to rename with the same "operation not permitted". This is once with -E and once without, same files, seemingly same wanted destination name:
C:\tmp\test>remv -Evv (a) $1b
 Processing '.\bla-has-dot.txt'.
 Renaming     '.\bla-has-dot.txt' to '.\blab-habs-dot.txt' ... error: operation not permitted
 Processing '.\file.with.dots.txt'.
 [STATS] Renamed 0 files (1 failed, 1 skipped).

C:\tmp\test>remv -vv (a) $1b
 Processing '.\bla-has-dot.txt'.
 Renaming     '.\bla-has-dot.txt' to '.\blab-habs-dot.txt' ... Successfully renamed .\bla-has-dot.txt to .\blab-habs-dot.txt.
 Processing '.\file.with.dots.txt'.
 [STATS] Renamed 1 files (0 failed, 1 skipped).

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #6 on: January 07, 2019, 04:00 PM »
 :huh:

You truly make me sad. I'm on it (but off tomorrow)...
I'll report back.

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #7 on: January 07, 2019, 04:49 PM »
Now, now.

> .\a -Evv "hpp" "npp"
 Processing '.\a.exe'.
 Processing '.\constants.hpp'.
 Processing '.\filestats.hpp'.
 Processing '.\help.hpp'.
 Processing '.\remv.cpp'.
 Processing '.\remv.hpp'.
 [STATS] Renamed 0 files (0 failed, 6 skipped).

> .\a -vv "hpp" "npp"
 Processing '.\a.exe'.
 Processing '.\constants.hpp'.
 Renaming     '.\constants.hpp' to '.\.\constants.npp' ... Successfully renamed .\constants.hpp to .\.\constants.npp.
 Processing '.\filestats.hpp'.
 Renaming     '.\filestats.hpp' to '.\.\filestats.npp' ... Successfully renamed .\filestats.hpp to .\.\filestats.npp.
 Processing '.\help.hpp'.
 Renaming     '.\help.hpp' to '.\.\help.npp' ... Successfully renamed .\help.hpp to .\.\help.npp.
 Processing '.\remv.cpp'.
 Processing '.\remv.hpp'.
 Renaming     '.\remv.hpp' to '.\.\remv.npp' ... Successfully renamed .\remv.hpp to .\.\remv.npp.
 [STATS] Renamed 4 files (0 failed, 2 skipped).

Granted, the ".\.\" part looks inconvenient, but good enough.  ;D
I'll look into it on Wednesday again. Checking in, updating the RAR and leaving you alone for today/tomorrow. :)

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #8 on: January 07, 2019, 06:07 PM »
remv 1.1.1 from the OP.

Some observations, which might be attributable to my appalling lack of RegEx knowledge.

The test subjects in their original positions and a dry run:
2019-01-08 10_49_52-C__WINDOWS_system32_cmd.exe.pngremv: Rename files (and directories) with regular expressions

2019-01-08 10_50_52-C__WINDOWS_system32_cmd.exe.pngremv: Rename files (and directories) with regular expressions
  • Output is munged:
    • single line output
    • the whole .\.\ thing as well as '.\dir\.\dir\file'
  • The executable has renamed itself, it would be better if it excluded itself from the operation, (no matter what name the executable has been given).
  • More importantly, the file renaming failed and this, (as indicated by the output), is because the directories were renamed first thus any files within those directories were now non-existent.  I would suggest the renaming start at the lowest level and work up.

2019-01-08 10_51_47-C__WINDOWS_system32_cmd.exe.pngremv: Rename files (and directories) with regular expressions
  • Same results as above but the output is now multi-line.
  • It would be better, (I think), if instead of saying Processing 'something' against items that don't match, it said Skipped 'something'.  It would help with quickly scanning the output to see what was skipped or having the output redirected to a file and searching that for Skipped.
« Last Edit: January 07, 2019, 06:39 PM by 4wd »

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #9 on: January 09, 2019, 02:40 PM »
Why do I even publish software one year in advance if people don't test it before it's too late?  ;D

Not renaming the .exe would require to write one function per platform, as C++ does not have a cross-platform way to find the "current .exe path" as far as I know.  :huh:
Coming closer with version 1.2.0... (attaching above.)

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #10 on: January 09, 2019, 04:30 PM »
Why do I even publish software one year in advance if people don't test it before it's too late?  ;D

I was having a break from thinking last year  :)

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #11 on: January 10, 2019, 09:25 AM »
I don't think the program should exclude itself in any way. I'm fairly confident no other file renamer/mover does so.
Any file that actually fits the pattern, fits the pattern, and should be processed.
For most normal operation, that's a non-issue anyway, the program will most likely not be in the relevant directory. When it is, outside of specifically the case of testing the program, then if it fits the pattern it's very likely to be intentional, by someone trying to move/rename it specifically (someone placed it in its own directory), or a bunch of portable utilities it's placed with (someone placed it in a utils/bin/programs folder).

Jibz

  • Developer
  • Joined in 2005
  • ***
  • Posts: 1,187
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #12 on: January 10, 2019, 02:22 PM »
If you allow moving between folders as well as renaming you may get into some interesting issues.

One problem is that you are not guaranteed what order you get files and folders in, so one run could have a move fail because the target file exists, while another can succeed because the file with the target name was processed earlier and moved.

For instance if you have x/x/x/ containing x/foo and x/x/foo, and you move foo to x/foo recursively, then if you process x/foo before recursing into x/x/, it will fail, but if you recurse into x/x/ and move x/x/foo first, then moving x/foo will later succeed.

Even worse, C++ does not guarantee if any files or folders created after you create the directory iterator show up in it, so you could potentially have a rename bomb if you rename for instance f(o+)x to f$1$1x.

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #13 on: January 10, 2019, 02:24 PM »
Version 1.2.0 should recurse backwards.  :-[

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #14 on: January 10, 2019, 03:04 PM »
If you allow moving between folders as well as renaming you may get into some interesting issues.

One problem is that you are not guaranteed what order you get files and folders in, so one run could have a move fail because the target file exists, while another can succeed because the file with the target name was processed earlier and moved.

For instance if you have x/x/x/ containing x/foo and x/x/foo, and you move foo to x/foo recursively, then if you process x/foo before recursing into x/x/, it will fail, but if you recurse into x/x/ and move x/x/foo first, then moving x/foo will later succeed.

Even worse, C++ does not guarantee if any files or folders created after you create the directory iterator show up in it, so you could potentially have a rename bomb if you rename for instance f(o+)x to f$1$1x.
There are a couple of things that can be done to help with these issues.
1. Don't rename on-the-fly. Prepare a full file-list first on one pass, then rename files on the list on a second pass. Should be relatively easy to do, and prevents a rename bomb since a newly created name won't be caught again.
2. Do the rename "virtually" first, on the names in the file-list, checking if the result is in the file list, and if so then delay that file to a subsequent pass, and only actually rename files that successfully went through the check. Possibly repeat, as long as in each pass something does get renamed. Complicates things, possibly significantly. But won't fail to rename a file to something that existed originally but should be renamed/moved anyway later (e.g. running your "f(o+)x" to "f$1$1x" on a folder with "fox" and "foox").

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #15 on: January 10, 2019, 03:31 PM »
Hmmm... With 1.2.0 , -nvv shows skipped files, -nv doesn't show skipped files, but does add a newline for each one.
C:\tmp\test>remv -nv f(o+)x f$1$1x
 Can't rename .\fox' to '.\foox' - file exists.
 Would rename '.\foox' to '.\foooox' ...




 [STATS] The simulation suggested 1 renames. Note that some of them might fail.

C:\tmp\test>remv -nvv f(o+)x f$1$1x
 Can't rename .\fox' to '.\foox' - file exists.
 Would rename     '.\foox' to '.\foooox' ...
 Skipping         '.\file.with.dots.txt' ...
 Skipping         '.\blab-habs-dot.txt' ...
 Skipping         '.\b' ...
 Skipping         '.\a' ...
 [STATS] The simulation suggested 1 renames. Note that some of them might fail.
after deleting the other files:
C:\tmp\test>remv -nvv f(o+)x f$1$1x
 Can't rename .\fox' to '.\foox' - file exists.
 Would rename     '.\foox' to '.\foooox' ...
 [STATS] The simulation suggested 1 renames. Note that some of them might fail.

C:\tmp\test>remv -nv f(o+)x f$1$1x
 Can't rename .\fox' to '.\foox' - file exists.
 Would rename '.\foox' to '.\foooox' ...
 [STATS] The simulation suggested 1 renames. Note that some of them might fail.

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #16 on: January 10, 2019, 03:36 PM »
"-vv" shows more stats indeed. This is intended. :)
OK, the newline is ugly, granted...

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #17 on: January 10, 2019, 05:40 PM »
remv 1.2.0

OK, something seems to be wrong:

Initial structure:
2019-01-11 09_46_57-K__test.pngremv: Rename files (and directories) with regular expressions

Code: Text [Select]
  1. K:\>remv -Ervvns o(.+)e(.+)$ d$1$2 test
  2.  Would rename     'test\two\one\two.pdf' to 'test\twd\on\two.pdf' ...
  3.  Skipping   'test\two\one'.
  4.  Skipping   'test\two'.
  5.  Skipping         'test\three\two\one.pdf' ...
  6.  Skipping   'test\three\two\one'.
  7.  Skipping   'test\three\two'.
  8.  Skipping         'test\three\three.pdf' ...
  9.  Skipping   'test\three'.
  10.  Would rename     'test\one\two\harry.pdf' to 'test\dn\two\harry.pdf' ...
  11.  Skipping   'test\one\two'.
  12.  Would rename     'test\one\three\one\fred.pdf' to 'test\dne\three\one\frd.pdf' ...
  13.  Skipping   'test\one\three\one'.
  14.  Would rename     'test\one\three\evie.pdf' to 'test\dne\three\vie.pdf' ...
  15.  Skipping   'test\one\three'.
  16.  Skipping   'test\one'.
  17.  [STATS] The simulation suggested 4 renames. Note that some of them might fail.

Taken from the top for the 'Would rename ...' lines, I would have thought given o(.+)e(.+)$ and ignoring extensions:
Would rename     'test\two\one\two.pdf' to 'test\twd\on\two.pdf' ...
'test\two\one\two.pdf' -> 'test\two\one\two.pdf'  - Skip it

Would rename     'test\one\two\harry.pdf' to 'test\dn\two\harry.pdf' ...
'test\one\two\harry.pdf' -> 'test\one\two\harry.pdf'  - Skip it

Would rename     'test\one\three\one\fred.pdf' to 'test\dne\three\one\frd.pdf' ...
'test\one\three\one\fred.pdf' -> 'test\one\three\one\fred.pdf' - Skip it

Would rename     'test\one\three\evie.pdf' to 'test\dne\three\vie.pdf' ...
'test\one\three\evie.pdf' -> 'test\one\three\evie.pdf' - Skip it

ie. None of them match the given criteria.

The actual result:
Code: Text [Select]
  1. K:\>remv -Ervvs o(.+)e(.+)$ d$1$2 test
  2.  Renaming     'test\two\one\two.pdf' to 'test\twd\on\two.pdf' ... error: operation not permitted
  3.  Skipping   'test\two\one'.
  4.  Skipping   'test\two'.
  5.  Skipping         'test\three\two\one.pdf' ...
  6.  Skipping   'test\three\two\one'.
  7.  Skipping   'test\three\two'.
  8.  Skipping         'test\three\three.pdf' ...
  9.  Skipping   'test\three'.
  10.  Renaming     'test\one\two\harry.pdf' to 'test\dn\two\harry.pdf' ... error: operation not permitted
  11.  Skipping   'test\one\two'.
  12.  Renaming     'test\one\three\one\fred.pdf' to 'test\dne\three\one\frd.pdf' ... error: operation not permitted
  13.  Skipping   'test\one\three\one'.
  14.  Renaming     'test\one\three\evie.pdf' to 'test\dne\three\vie.pdf' ... error: operation not permitted
  15.  Skipping   'test\one\three'.
  16.  Skipping   'test\one'.
  17.  [STATS] Renamed 0 files (4 failed, 11 skipped).


Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #18 on: January 10, 2019, 06:56 PM »
Hmm, that might be fixed with a simple call to create_directories before renaming, so the target directories will be created even if the original directories didn't match your regex. But that would lead to empty folders when the files from them have been moved.

I'm currently experimenting a bit:

> .\a.exe -Erv "remv" "romv"
 Renaming       '.\remv.hpp' to '.\romv.hpp' ...
   error [rn]: operation not permitted
 Renaming       '.\remv.cpp' to '.\romv.cpp' ...
   error [rn]: operation not permitted
 [STATS] Renamed 0 files (2 failed, 4 skipped).

> .\a.exe -rv "remv" "romv"
 Renaming       '.\remv.hpp' to '.\romv.hpp' ...
 Renaming       '.\remv.cpp' to '.\romv.cpp' ...
 [STATS] Renamed 2 files (0 failed, 4 skipped).

Something about the -E flag is fishy.  :huh:
I'll look into it tomorrow or on Monday (I'm visiting friends over the weekend). Attaching version 1.2.1 with a broken -E flag above for the time being.

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #19 on: January 10, 2019, 07:16 PM »
FWIW, this is a small PowerShell script I put together to check against what I was testing above:

Code: PowerShell [Select]
  1. # Folder to act on
  2. $folder = 'K:\test-ps'
  3. # Regex to match
  4. $regexMatch = "o(.+)e(.+)$"
  5. # Regex to replace
  6. $regexReplace = "d`$1`$2" # Must remember to escape the back references DOH!
  7. # Ignore extension
  8. $ignoreExt = $true
  9. # Grab the directory tree
  10. $a = Get-ChildItem $folder -recurse
  11. # Sort by folder depth
  12. $b = ($a | Select-Object FullName, @{Name="FolderDepth";Expression={$_.DirectoryName.Split('\').Count}} | Sort-Object -Descending FolderDepth,FullName)
  13. # Loop through each file/dir name seeing if it matches and output the result
  14. for ($i = 0; $i -lt $b.Count; $i++) {
  15.   # Output the last part of the path we're testing
  16.   Write-Host (Split-Path $b[$i].FullName -Leaf) -NoNewline
  17.   if ($ignoreExt) {
  18.     # Ignoring extension
  19.     # Grab the last part of the path (file/folder)
  20.     $t1 = (Split-Path $b[$i].FullName -Leaf)
  21.     # Grab name without extension and replace matches
  22.     $newName = ([io.path]::GetFileNameWithoutExtension($t1) -replace $regexMatch, $regexReplace)
  23.     # Output result
  24.     Write-Host " -> $($newName)$([io.path]::GetExtension($t1))"
  25.   } else {
  26.     # Include extension
  27.     # Grab the last part of the path (file/folder) and replace matches
  28.     $newName = ((Split-Path $b[$i].FullName -Leaf) -replace $regexMatch, $regexReplace)
  29.     # Output result
  30.     Write-Host " -> $($newName)"
  31.   }
  32. }


Sample output
Code: Text [Select]
  1. PS Z:\test\_Coding Snacks> Z:\test\_Coding Snacks\remv-test.ps1
  2. fred.pdf -> fred.pdf
  3. two.pdf -> two.pdf
  4. one.pdf -> one.pdf
  5. harry.pdf -> harry.pdf
  6. evie.pdf -> evie.pdf
  7. three.pdf -> three.pdf
  8. one -> one
  9. two -> two
  10. one -> one
  11. two -> two
  12. three -> three
  13. two -> two
  14. one -> one
  15. three -> three
  16. one -> one


No guarantee it's correct either  ;)
« Last Edit: January 10, 2019, 07:44 PM by 4wd »

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #20 on: January 10, 2019, 07:20 PM »
Nice. I haven't really done much with the PowerShell yet.  :Thmbsup:

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #21 on: January 10, 2019, 07:38 PM »
Unfortunately, I kind of got the $regexReplace wrong :-[
Would have failed if $ignoreExt = $false

Need to directly input the Regex replacement string because of the way PowerShell handles references, (specifically using $ with ' or ") - adjusted script.

Probably a way around it but my brain isn't up to it atm.


Fixed, needed to escape the back references with `
« Last Edit: January 10, 2019, 07:45 PM by 4wd »

yarond

  • Supporting Member
  • Joined in 2011
  • **
  • default avatar
  • Posts: 11
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #22 on: January 13, 2019, 11:11 AM »
Hmm, that might be fixed with a simple call to create_directories before renaming, so the target directories will be created even if the original directories didn't match your regex. But that would lead to empty folders when the files from them have been moved.
The program is already set to rename/move files, not directories by themselves.
So leaving empty directories behind is both the correct, and expected, behavior. Moving everything out of a directory doesn't necessarily mean that the directory should be deleted, empty directories are a valid entity.

If you want to, it's of course possible to add an optional parameter to check if any directory is being emptied during the run (keep track of location for any file that was moved, and after processing everything check if any of the locations are empty), and then delete them. But, again, while that could certainly be nice, I think it's not required, and it's perfectly fine and normal for empty directories to be left behind if the files inside them were moved elsewhere.

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #23 on: January 13, 2019, 04:32 PM »
Hmm, that might be fixed with a simple call to create_directories before renaming, so the target directories will be created even if the original directories didn't match your regex.

BTW, I don't know if you noticed but it was suggesting directory name changes even though I hadn't specified the -d parameter.

Actually, looking at the results  again, I would say it's matching against the complete path instead of the individual components of that path.
« Last Edit: January 13, 2019, 04:49 PM by 4wd »

Tuxman

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 2,466
    • View Profile
    • Donate to Member
Re: remv: Rename files (and directories) with regular expressions
« Reply #24 on: January 14, 2019, 01:17 PM »
Yes, it does - so you can match subfolders.  :)

I don't know if you noticed but it was suggesting directory name changes even though I hadn't specified the -d parameter.

If they are a part of the path to a regular file, yes. You cannot rename a whole directory without a file in it though.
I could make the non-d call skip subfolders, but then -d would be the same thing as not using -r, or am I mistaken?