12

I have a directory with a bunch of files with names like:

001234.jpg
001235.jpg
004729342.jpg

I want to remove the leading zeros from all file names, so I'd be left with:

1234.jpg
1235.jpg
4729342.jpg

I've been trying different configurations of sed, but I can't find the proper syntax. Is there an easy way to list all files in the directory, pipe it through sed, and either move or copy them to the new file name without the leading zeros?

Foggzie
  • 9,691
  • 1
  • 31
  • 48
George
  • 3,251
  • 7
  • 32
  • 39
  • 1
    Note: this will make sorting more difficult. – Evan Carroll Jan 15 '10 at 21:42
  • 1
    With GNU coreutils, `ls -v` will sort numbers naturally (using the Glibc extensions `versionsort(3)/strverscmp(3)`). But yes, in general, changing the numeric portions of the filenames to no longer line up by length does change normal collation order. – ephemient Jan 15 '10 at 22:07

8 Answers8

18
for FILE in `ls`; do mv $FILE `echo $FILE | sed -e 's:^0*::'`; done
cyborg
  • 5,638
  • 1
  • 19
  • 25
  • 2
    You don't need to (and shouldn't) use `ls` like this. Do it this way: `for FILE in *` – Dennis Williamson Jan 15 '10 at 23:19
  • 1
    this is a bad example. first using ls, and then never quote your variables – ghostdog74 Jan 15 '10 at 23:56
  • I don't see any problem with using ls. You can substitute it for the find command suggested below or any other command. Since it works I don't really see what your justifications are other than stylistic, which when it comes to one line shell scripts seems a little pointless. – cyborg Jan 16 '10 at 12:09
  • * will do the right thing, `ls` sometimes will not (for example if a file has a space in its name, this script will not work). – Justin Smith Jan 17 '10 at 02:57
  • My experience has not shown that sort of behaviour. If specifying the list myself the items will need to be separated by a line break. – cyborg Jan 17 '10 at 09:36
12

sed by itself is the wrong tool for this: you need to use some shell scripting as well.

Check Rename multiple files with Linux page for some ideas. One of the ideas suggested is to use the rename perl script:

rename 's/^0*//' *.jpg
kenorb
  • 155,785
  • 88
  • 678
  • 743
Simon Nickerson
  • 42,159
  • 20
  • 102
  • 127
8

In Bash, which is likely to be your default login shell, no external commands are necessary.

shopt -s extglob
for i in 0*[^0]; do mv "$i" "${i##*(0)}"; done
ephemient
  • 198,619
  • 38
  • 280
  • 391
1

Try using sed, e.g.:

sed -e 's:^0*::'

Complete loop:

for f in `ls`; do
   mv $f $(echo $f | sed -e 's:^0*::')
done
kenorb
  • 155,785
  • 88
  • 678
  • 743
eduffy
  • 39,140
  • 13
  • 95
  • 92
  • This is probably good enough for George's situation, but in a different environment one might wish to handle the special case where the filename is all zeroes. – Jim Lewis Jan 15 '10 at 21:03
  • 3
    There is absolutely no reason to use `for f in \`ls\`` instead of the much safer and more efficient `for f in *`. – ephemient Jan 15 '10 at 21:42
1

Maybe not the most elegant but it will work.

for i in 0*
do
mv "${i}" "`expr "${i}" : '0*\(.*\)'`"
done
ephemient
  • 198,619
  • 38
  • 280
  • 391
jml3310
  • 11
  • 1
0

I dont know sed at all but you can get a listing by using find:

find -type f -name *.jpg

so with the other answer it might look like

find . -type f -name *.jpg | sed -e 's:^0*::'

but i dont know if that sed command holds up or not.

prodigitalson
  • 60,050
  • 10
  • 100
  • 114
0

Here's one that doesn't require sed:

for x in *.jpg ; do let num="10#${x%%.jpg}"; mv $x ${num}.jpg ;  done

Note that this ONLY works when the filenames are all numbers. You could also remove the leading zeros using the shell:

for a in *.jpg ; do dest=${a/*(0)/} ; mv $a $dest ; done
Kaleb Pederson
  • 45,767
  • 19
  • 102
  • 147
0

In Bash shell you can do:

shopt -s nullglob
for file in 0*.jpg
do
   echo mv "$file" "${file##*0}"
done
kenorb
  • 155,785
  • 88
  • 678
  • 743
ghostdog74
  • 327,991
  • 56
  • 259
  • 343