4

I've built a command to delete all leading whitespace of all folder/file names in a directory (with subdirectories).

find /dir/* -depth -execdir rename 's/^\s+//g' * "{}" \; 

It works in some small directories (with some subdirectories) but it took very long for large directories. I see that the command is executed more times than necessary, but I don't know why.

Can somebody suggest how to speed it up?

/edit: I'am useing Debian 8.2 as OS.

Dice
  • 41
  • 2
  • 3
    You might want to tweak you find command to return only names that start with space. Unless I am missing something, you are currently renaming all files. – Richard St-Cyr Dec 23 '15 at 00:25
  • Use `+` in place of `\;` so that it executes the `rename` command (is that the Perl-based `rename`) is executed once for a group of files, not once per file. (Plus, as Richard St-Cyr pointed out, don't attempt to rename files or directories that need don't need renaming.) – Jonathan Leffler Dec 23 '15 at 00:56
  • @RichardSt-Cyr Thanks for that suggestion. I thought my find command would just travel to every directory in /dir and then visit all subdirectories and then, execute my rename command in it. Do I've missunderstood how find works? oO JonathanLeffler Yeah its the pearl rename command. hmm ok then I need some more research of how find works. I though that it would open a folder, execute the command and then opens the next folder... confusing^^ Thanks to both of you for your help :) – Dice Dec 23 '15 at 12:42

1 Answers1

1

I think you've misunderstood how the -execdir parameter of find works. The rename command will be run from the subdirectory containing the matched file, but it will still be called for every matched file. Your rename arguments include the * wildcard, so in each subdirectory that has N files, you'll call rename on N^2 files. (+1 for the "{}" filled in by find.)

The problem is, I think your rename regex only works because of the *. I don't think it will actually match the "{}" part.

So summarize (including comments from above):

  1. Use -regex to find only the files you want to rename.
  2. Use + instead of ; to group files.
  3. Drop the wildcard *.
  4. Fix the rename regex to operate on the basename of the matched files (find will pass on the paths with ./ prefix).

An alternative might be to find all subdirectories that have a file/folder beginning with space, and then running rename * in just those directories. Gut feeling says the first approach is more efficient, but it probably depends on the number and distribution of the matched files.

(Sorry, I did not have the time to actually write the one-liner for you!)

Jani
  • 853
  • 8
  • 20