I would like to rename files within each sub-directory by adding the name of the sub-directory. Following the answer from Rename files by adding their parent folder name, I tried:
rename 's/(.*)\//$1\/$1_/' */*
However for lots of sub-directories it doesn't work. I have 13,000 sub-directories each containing about 300 files. I get
-bash: /usr/bin/rename: Argument list too long
I tried:
ls | xargs rename 's/(.*)\//$1\/$1_/' */*
find . -maxdepth 1 -type f -print0 | xargs rename 's/(.*)\//$1\/$1_/' */*
Both give the same error:
-bash: /usr/bin/xargs: Argument list too long
EDIT
xargs -L rename 's/(.*)\//$1\/$1_/' */*
xargs -L1 rename 's/(.*)\//$1\/$1_/' */*
Same error:
-bash: /usr/bin/xargs: Argument list too long
As @egmont noted, giving the paths (
*/*
) as argument(s) toxargs
is wrong. This command reads file names from the standard input instead of arguments, so issuingxargs
without any standard input (the EDIT section of the question) is useless.Solution using
ls
andxargs
Check if you can just
ls
all the paths in question.If yes, you can use a corrected version of your 2) option:
Solution using
find
If you get an error from the
ls
call, you can still usefind
.-exec
option which works similarly toxargs
, so we’ll not needxargs
in this case at all.ls */*
, use the options-mindepth 2 -maxdepth 2
.The corrected version of the 3) option would be:
The argument placeholder together with an escaped semicolon (
{} \;
) ensures thatrename
is run just for a single file at a time, similarly toxargs -L1
. This will prevent the original issue with too many files at once.Dry run and actual rename
You can check the result using the
-n
option I included afterrename
to just list the renames it would do. To actually launch the rename operation, remove the-n
option.