1

This question already has an answer here:

I was hoping this would work:

$ find . -type f -exec basename {} \; | while EFS= read -r f; do echo "${f##[0-9]}"; done 

But, for example, for files named as:

1foo
11bar

it returns:

foo
1bar

when

foo
bar

is expected.

PS: ultimately, I want to mv "$f" to the modified name (and also do other modifications)

EDIT:

PS2: it's not a duplicate if you consider PS. Anyways, the answer marked check satisfies me.

marked as duplicate by Fiximan, don_crissti, Jeff Schaller, schily, Kiwy Oct 25 '18 at 9:35

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • The title says "beginning of file" but your code is gathering filenames and then renaming them. Also, unsetting "EFS" appears to be a typo for unsetting "IFS" – Jeff Schaller Oct 24 '18 at 21:36
  • Your solution necessitates to know in advance the number of digits. Is there not a more general way? Why doesn't ## take care of it in the parameter expansion? – Erwann Oct 24 '18 at 21:37
  • Yes, I meant filename, sorry. – Erwann Oct 24 '18 at 21:38
  • 1
    Do you care how it's done? Do you have a "rename" utility installed? – Jeff Schaller Oct 24 '18 at 21:39
  • I was using EFS, and replacing it by IFS works the same. I'd like to understand why my solution doesn't work, but I'll accept rename as well (it is installed) – Erwann Oct 24 '18 at 21:43
2

find . -type f -exec basename {} \; | while IFS= read -r f; do echo "${f##+([0-9])}"; done should provide the desired results.

This uses extended pattern matching operators, of which +() means match one or more.

Additional information can be found in the Pattern Matching section of the bash man page.

  • 4
    You need to enable the extglob option to make this work. – RudiC Oct 24 '18 at 22:00
5

If rename (sometimes called prename) is an option:

find . -name '[[:digit:]]*' -type f -exec rename 's:^(.*/)\d+([^/]*)\z:\1\2:s' {} +

explanation:

  • ( ) patterns in parentheses are saved and can be recalled by the number of appearance
  • .*/ the directory portion must be preserved
  • ([^/]*)\z: all non-/ characters till the end of the subject.
  • \1\2 reprint the captured directory and everything past the digits in the output name

You can use the -n option in rename to do a dry-run for checking the results first.

  • That won't work. The file names seen by rename start with ./, not digits. If you replace -exec with -execdir, with some find implementations including GNU find, that will still be ./. – Stéphane Chazelas Oct 25 '18 at 9:41
  • @StéphaneChazelas good point - updated. – Fiximan Oct 25 '18 at 12:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.