remove first characters if its â0â from all files
Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
i have few folder:
1
2
3
4
5
so in each folder i have files like
00123.mp3
00133.mp3
00150.mp3
so i want to remove all 0 if they are at beginning of filename
i tried this
for file in *; do echo mv "$file" "$file//[ ()@0]/"; done
but it remove all 0 in begenning and inside filename (i need just in begining)
also this is not working in subdirectory
linux rename mv
add a comment |Â
up vote
1
down vote
favorite
i have few folder:
1
2
3
4
5
so in each folder i have files like
00123.mp3
00133.mp3
00150.mp3
so i want to remove all 0 if they are at beginning of filename
i tried this
for file in *; do echo mv "$file" "$file//[ ()@0]/"; done
but it remove all 0 in begenning and inside filename (i need just in begining)
also this is not working in subdirectory
linux rename mv
2
Which shell are you using? bash with shell optionextglob
enabled supports"$file##+(0)"
to remove a leading sequence of one or more 0s I think
â steeldriver
Feb 7 at 21:17
1
Note that it doesn't work in subdirectories because the asterisk wildcard is not recursive - it will always match items in the specified directory only. This is one thing all shells I'm aware of agree on. If you want to go into subdirectories, you need to figure out (and possibly enable) your shell's equivalent of globstar - likely some variation on**
.
â brhfl
Feb 7 at 21:24
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
i have few folder:
1
2
3
4
5
so in each folder i have files like
00123.mp3
00133.mp3
00150.mp3
so i want to remove all 0 if they are at beginning of filename
i tried this
for file in *; do echo mv "$file" "$file//[ ()@0]/"; done
but it remove all 0 in begenning and inside filename (i need just in begining)
also this is not working in subdirectory
linux rename mv
i have few folder:
1
2
3
4
5
so in each folder i have files like
00123.mp3
00133.mp3
00150.mp3
so i want to remove all 0 if they are at beginning of filename
i tried this
for file in *; do echo mv "$file" "$file//[ ()@0]/"; done
but it remove all 0 in begenning and inside filename (i need just in begining)
also this is not working in subdirectory
linux rename mv
asked Feb 7 at 20:33
arlind
82
82
2
Which shell are you using? bash with shell optionextglob
enabled supports"$file##+(0)"
to remove a leading sequence of one or more 0s I think
â steeldriver
Feb 7 at 21:17
1
Note that it doesn't work in subdirectories because the asterisk wildcard is not recursive - it will always match items in the specified directory only. This is one thing all shells I'm aware of agree on. If you want to go into subdirectories, you need to figure out (and possibly enable) your shell's equivalent of globstar - likely some variation on**
.
â brhfl
Feb 7 at 21:24
add a comment |Â
2
Which shell are you using? bash with shell optionextglob
enabled supports"$file##+(0)"
to remove a leading sequence of one or more 0s I think
â steeldriver
Feb 7 at 21:17
1
Note that it doesn't work in subdirectories because the asterisk wildcard is not recursive - it will always match items in the specified directory only. This is one thing all shells I'm aware of agree on. If you want to go into subdirectories, you need to figure out (and possibly enable) your shell's equivalent of globstar - likely some variation on**
.
â brhfl
Feb 7 at 21:24
2
2
Which shell are you using? bash with shell option
extglob
enabled supports "$file##+(0)"
to remove a leading sequence of one or more 0s I thinkâ steeldriver
Feb 7 at 21:17
Which shell are you using? bash with shell option
extglob
enabled supports "$file##+(0)"
to remove a leading sequence of one or more 0s I thinkâ steeldriver
Feb 7 at 21:17
1
1
Note that it doesn't work in subdirectories because the asterisk wildcard is not recursive - it will always match items in the specified directory only. This is one thing all shells I'm aware of agree on. If you want to go into subdirectories, you need to figure out (and possibly enable) your shell's equivalent of globstar - likely some variation on
**
.â brhfl
Feb 7 at 21:24
Note that it doesn't work in subdirectories because the asterisk wildcard is not recursive - it will always match items in the specified directory only. This is one thing all shells I'm aware of agree on. If you want to go into subdirectories, you need to figure out (and possibly enable) your shell's equivalent of globstar - likely some variation on
**
.â brhfl
Feb 7 at 21:24
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
2
down vote
accepted
If you are using bash, this script will do what you ask for:
#!/bin/bash
shopt -s extglob
while IFS= read -d '' f ; do
file=$f##*/
dir="$f%/*/"
echo
mv "$dir$file" "$dir$file##+(0)"
done < <(find . -type f -name '0*.mp3' -print0)
comment the echo
line to actually perform the mv
command(s) once you agree with the list of files to move.
Or this sh version for portability:
#!/bin/sh
find . -type f -name '0*.mp3' -print |
while IFS= read f; do
file=$f##*/
dir="$f%/*/"
f2=$file; until [ "$f2" = "$f2#0" ]; do f2=$f2#0; done
echo
mv "$f" "$dir$f2"
done
Note thatmv
inherits the stdin of the loop, so the pipe fromfind
.-i
would cause it to read the answer to confirmation prompts from the output offind
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or usemv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
@StéphaneChazelas Can not get themv -i
to work, just removed it.
â Isaac
Feb 8 at 1:56
add a comment |Â
up vote
2
down vote
Since your question is tagged Linux, you could use rename
or prename
command (note that prename
is not deprecated, though, but still works). In either case they're perl script for pattern-based renaming.
With group matching and using *.mp3
glob to pass only .mp3
files, you can do this:
$ prename -nv 's/(^0*)(.*).mp3/$2.mp3/' *.mp3
Deprecated program in use: rename as shipped with the Debian perl package will be removed after the release of stretch. Please install the separate 'rename' package which will provide the same command.
000004500.mp3 renamed as 4500.mp3
00123.mp3 renamed as 123.mp3
00133.mp3 renamed as 133.mp3
00150.mp3 renamed as 150.mp3
Note that -n
and -v
are for dry run and verbose output; testing only. Remove -n
for actual renaming to take effect.
In case you are confused about rename
vs prename
, you can read the corresponding answer that clears up the confusion, but...I would recommend that you just don't bother with that. Too convoluted :) The point is that in either case it works as shown, unless you're using ksh
shell.
Recursive way to rename files in subfolders would be via find
, however that requires a bit of acrobatics with substitution pattern to handle preceding items in the file path as provided by find
.
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ;
The above command performed as follows in a test case:
$ find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ; 2>/dev/null
./testdir/000004500.mp3 renamed as ./testdir/4500.mp3
./testdir/00150.mp3 renamed as ./testdir/150.mp3
./testdir/00133.mp3 renamed as ./testdir/133.mp3
./testdir/00123.mp3 renamed as ./testdir/123.mp3
Minor improvement could be to specify d
, the digit class:
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's//0*(d*.mp3)//$1/' ;
Stéphane Chazelas mentioned in the comments possibility where /0/1.mp3
could be accidentally rename to .//1.mp3
. I've taken couple test cases; ./testdir/0/000987.mp3 renamed as ./testdir/0/987.mp3
and ./testdir/007/00123.mp3 renamed as ./testdir/007/123.mp3
were the results. I think greedy matching of 0*
does the trick.
He also suggested in the comments adding [^/]
in filename pattern matching. This is a good idea since Unix filenames cannot have backslashes in them; paths can but not individual files. However, I am not quite sure how to better implement this and still have no suggestion on matching 0.mp3
or 000.mp3
types of filenames.
The recursive one won't work because^0
will never match because the paths start with./
.
â Stéphane Chazelas
Feb 8 at 0:12
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
There's a risk it could rename things like./0/1.mp3
to.//1.mp3
(or./0.mp3
to./mp3
, see my answer). You may want something likes/0*([0-9][^/]*.mp3)z$2
(untested)
â Stéphane Chazelas
Feb 8 at 0:29
The greedy.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using-execdir
instead of-exec
.
â ilkkachu
Feb 8 at 8:46
add a comment |Â
up vote
1
down vote
With zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '0#(*.mp3)' '$1'
(remove -n
(dry-run) when happy).
The #
glob operator in zsh
is like the *
regular expression operator.
Note that it would rename 0000.mp3
to .mp3
. To avoid that you can change it do:
zmv -n '0#([0-9]*.mp3)' '$1'
Recursively:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2'
To also remove the () @
characters as your example suggests you may want to do:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2//[() @]'
(It would however not remove those characters from file names that don't start with a digit).
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
If you are using bash, this script will do what you ask for:
#!/bin/bash
shopt -s extglob
while IFS= read -d '' f ; do
file=$f##*/
dir="$f%/*/"
echo
mv "$dir$file" "$dir$file##+(0)"
done < <(find . -type f -name '0*.mp3' -print0)
comment the echo
line to actually perform the mv
command(s) once you agree with the list of files to move.
Or this sh version for portability:
#!/bin/sh
find . -type f -name '0*.mp3' -print |
while IFS= read f; do
file=$f##*/
dir="$f%/*/"
f2=$file; until [ "$f2" = "$f2#0" ]; do f2=$f2#0; done
echo
mv "$f" "$dir$f2"
done
Note thatmv
inherits the stdin of the loop, so the pipe fromfind
.-i
would cause it to read the answer to confirmation prompts from the output offind
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or usemv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
@StéphaneChazelas Can not get themv -i
to work, just removed it.
â Isaac
Feb 8 at 1:56
add a comment |Â
up vote
2
down vote
accepted
If you are using bash, this script will do what you ask for:
#!/bin/bash
shopt -s extglob
while IFS= read -d '' f ; do
file=$f##*/
dir="$f%/*/"
echo
mv "$dir$file" "$dir$file##+(0)"
done < <(find . -type f -name '0*.mp3' -print0)
comment the echo
line to actually perform the mv
command(s) once you agree with the list of files to move.
Or this sh version for portability:
#!/bin/sh
find . -type f -name '0*.mp3' -print |
while IFS= read f; do
file=$f##*/
dir="$f%/*/"
f2=$file; until [ "$f2" = "$f2#0" ]; do f2=$f2#0; done
echo
mv "$f" "$dir$f2"
done
Note thatmv
inherits the stdin of the loop, so the pipe fromfind
.-i
would cause it to read the answer to confirmation prompts from the output offind
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or usemv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
@StéphaneChazelas Can not get themv -i
to work, just removed it.
â Isaac
Feb 8 at 1:56
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
If you are using bash, this script will do what you ask for:
#!/bin/bash
shopt -s extglob
while IFS= read -d '' f ; do
file=$f##*/
dir="$f%/*/"
echo
mv "$dir$file" "$dir$file##+(0)"
done < <(find . -type f -name '0*.mp3' -print0)
comment the echo
line to actually perform the mv
command(s) once you agree with the list of files to move.
Or this sh version for portability:
#!/bin/sh
find . -type f -name '0*.mp3' -print |
while IFS= read f; do
file=$f##*/
dir="$f%/*/"
f2=$file; until [ "$f2" = "$f2#0" ]; do f2=$f2#0; done
echo
mv "$f" "$dir$f2"
done
If you are using bash, this script will do what you ask for:
#!/bin/bash
shopt -s extglob
while IFS= read -d '' f ; do
file=$f##*/
dir="$f%/*/"
echo
mv "$dir$file" "$dir$file##+(0)"
done < <(find . -type f -name '0*.mp3' -print0)
comment the echo
line to actually perform the mv
command(s) once you agree with the list of files to move.
Or this sh version for portability:
#!/bin/sh
find . -type f -name '0*.mp3' -print |
while IFS= read f; do
file=$f##*/
dir="$f%/*/"
f2=$file; until [ "$f2" = "$f2#0" ]; do f2=$f2#0; done
echo
mv "$f" "$dir$f2"
done
edited Feb 8 at 1:51
answered Feb 7 at 23:31
Isaac
6,6381734
6,6381734
Note thatmv
inherits the stdin of the loop, so the pipe fromfind
.-i
would cause it to read the answer to confirmation prompts from the output offind
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or usemv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
@StéphaneChazelas Can not get themv -i
to work, just removed it.
â Isaac
Feb 8 at 1:56
add a comment |Â
Note thatmv
inherits the stdin of the loop, so the pipe fromfind
.-i
would cause it to read the answer to confirmation prompts from the output offind
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or usemv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
@StéphaneChazelas Can not get themv -i
to work, just removed it.
â Isaac
Feb 8 at 1:56
Note that
mv
inherits the stdin of the loop, so the pipe from find
. -i
would cause it to read the answer to confirmation prompts from the output of find
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or use mv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
Note that
mv
inherits the stdin of the loop, so the pipe from find
. -i
would cause it to read the answer to confirmation prompts from the output of find
. You could read the output of find on another fd (read <&3... done 3< <(find...
). Or use mv -i < /dev/tty...
â Stéphane Chazelas
Feb 8 at 0:15
@StéphaneChazelas Can not get the
mv -i
to work, just removed it.â Isaac
Feb 8 at 1:56
@StéphaneChazelas Can not get the
mv -i
to work, just removed it.â Isaac
Feb 8 at 1:56
add a comment |Â
up vote
2
down vote
Since your question is tagged Linux, you could use rename
or prename
command (note that prename
is not deprecated, though, but still works). In either case they're perl script for pattern-based renaming.
With group matching and using *.mp3
glob to pass only .mp3
files, you can do this:
$ prename -nv 's/(^0*)(.*).mp3/$2.mp3/' *.mp3
Deprecated program in use: rename as shipped with the Debian perl package will be removed after the release of stretch. Please install the separate 'rename' package which will provide the same command.
000004500.mp3 renamed as 4500.mp3
00123.mp3 renamed as 123.mp3
00133.mp3 renamed as 133.mp3
00150.mp3 renamed as 150.mp3
Note that -n
and -v
are for dry run and verbose output; testing only. Remove -n
for actual renaming to take effect.
In case you are confused about rename
vs prename
, you can read the corresponding answer that clears up the confusion, but...I would recommend that you just don't bother with that. Too convoluted :) The point is that in either case it works as shown, unless you're using ksh
shell.
Recursive way to rename files in subfolders would be via find
, however that requires a bit of acrobatics with substitution pattern to handle preceding items in the file path as provided by find
.
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ;
The above command performed as follows in a test case:
$ find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ; 2>/dev/null
./testdir/000004500.mp3 renamed as ./testdir/4500.mp3
./testdir/00150.mp3 renamed as ./testdir/150.mp3
./testdir/00133.mp3 renamed as ./testdir/133.mp3
./testdir/00123.mp3 renamed as ./testdir/123.mp3
Minor improvement could be to specify d
, the digit class:
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's//0*(d*.mp3)//$1/' ;
Stéphane Chazelas mentioned in the comments possibility where /0/1.mp3
could be accidentally rename to .//1.mp3
. I've taken couple test cases; ./testdir/0/000987.mp3 renamed as ./testdir/0/987.mp3
and ./testdir/007/00123.mp3 renamed as ./testdir/007/123.mp3
were the results. I think greedy matching of 0*
does the trick.
He also suggested in the comments adding [^/]
in filename pattern matching. This is a good idea since Unix filenames cannot have backslashes in them; paths can but not individual files. However, I am not quite sure how to better implement this and still have no suggestion on matching 0.mp3
or 000.mp3
types of filenames.
The recursive one won't work because^0
will never match because the paths start with./
.
â Stéphane Chazelas
Feb 8 at 0:12
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
There's a risk it could rename things like./0/1.mp3
to.//1.mp3
(or./0.mp3
to./mp3
, see my answer). You may want something likes/0*([0-9][^/]*.mp3)z$2
(untested)
â Stéphane Chazelas
Feb 8 at 0:29
The greedy.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using-execdir
instead of-exec
.
â ilkkachu
Feb 8 at 8:46
add a comment |Â
up vote
2
down vote
Since your question is tagged Linux, you could use rename
or prename
command (note that prename
is not deprecated, though, but still works). In either case they're perl script for pattern-based renaming.
With group matching and using *.mp3
glob to pass only .mp3
files, you can do this:
$ prename -nv 's/(^0*)(.*).mp3/$2.mp3/' *.mp3
Deprecated program in use: rename as shipped with the Debian perl package will be removed after the release of stretch. Please install the separate 'rename' package which will provide the same command.
000004500.mp3 renamed as 4500.mp3
00123.mp3 renamed as 123.mp3
00133.mp3 renamed as 133.mp3
00150.mp3 renamed as 150.mp3
Note that -n
and -v
are for dry run and verbose output; testing only. Remove -n
for actual renaming to take effect.
In case you are confused about rename
vs prename
, you can read the corresponding answer that clears up the confusion, but...I would recommend that you just don't bother with that. Too convoluted :) The point is that in either case it works as shown, unless you're using ksh
shell.
Recursive way to rename files in subfolders would be via find
, however that requires a bit of acrobatics with substitution pattern to handle preceding items in the file path as provided by find
.
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ;
The above command performed as follows in a test case:
$ find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ; 2>/dev/null
./testdir/000004500.mp3 renamed as ./testdir/4500.mp3
./testdir/00150.mp3 renamed as ./testdir/150.mp3
./testdir/00133.mp3 renamed as ./testdir/133.mp3
./testdir/00123.mp3 renamed as ./testdir/123.mp3
Minor improvement could be to specify d
, the digit class:
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's//0*(d*.mp3)//$1/' ;
Stéphane Chazelas mentioned in the comments possibility where /0/1.mp3
could be accidentally rename to .//1.mp3
. I've taken couple test cases; ./testdir/0/000987.mp3 renamed as ./testdir/0/987.mp3
and ./testdir/007/00123.mp3 renamed as ./testdir/007/123.mp3
were the results. I think greedy matching of 0*
does the trick.
He also suggested in the comments adding [^/]
in filename pattern matching. This is a good idea since Unix filenames cannot have backslashes in them; paths can but not individual files. However, I am not quite sure how to better implement this and still have no suggestion on matching 0.mp3
or 000.mp3
types of filenames.
The recursive one won't work because^0
will never match because the paths start with./
.
â Stéphane Chazelas
Feb 8 at 0:12
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
There's a risk it could rename things like./0/1.mp3
to.//1.mp3
(or./0.mp3
to./mp3
, see my answer). You may want something likes/0*([0-9][^/]*.mp3)z$2
(untested)
â Stéphane Chazelas
Feb 8 at 0:29
The greedy.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using-execdir
instead of-exec
.
â ilkkachu
Feb 8 at 8:46
add a comment |Â
up vote
2
down vote
up vote
2
down vote
Since your question is tagged Linux, you could use rename
or prename
command (note that prename
is not deprecated, though, but still works). In either case they're perl script for pattern-based renaming.
With group matching and using *.mp3
glob to pass only .mp3
files, you can do this:
$ prename -nv 's/(^0*)(.*).mp3/$2.mp3/' *.mp3
Deprecated program in use: rename as shipped with the Debian perl package will be removed after the release of stretch. Please install the separate 'rename' package which will provide the same command.
000004500.mp3 renamed as 4500.mp3
00123.mp3 renamed as 123.mp3
00133.mp3 renamed as 133.mp3
00150.mp3 renamed as 150.mp3
Note that -n
and -v
are for dry run and verbose output; testing only. Remove -n
for actual renaming to take effect.
In case you are confused about rename
vs prename
, you can read the corresponding answer that clears up the confusion, but...I would recommend that you just don't bother with that. Too convoluted :) The point is that in either case it works as shown, unless you're using ksh
shell.
Recursive way to rename files in subfolders would be via find
, however that requires a bit of acrobatics with substitution pattern to handle preceding items in the file path as provided by find
.
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ;
The above command performed as follows in a test case:
$ find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ; 2>/dev/null
./testdir/000004500.mp3 renamed as ./testdir/4500.mp3
./testdir/00150.mp3 renamed as ./testdir/150.mp3
./testdir/00133.mp3 renamed as ./testdir/133.mp3
./testdir/00123.mp3 renamed as ./testdir/123.mp3
Minor improvement could be to specify d
, the digit class:
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's//0*(d*.mp3)//$1/' ;
Stéphane Chazelas mentioned in the comments possibility where /0/1.mp3
could be accidentally rename to .//1.mp3
. I've taken couple test cases; ./testdir/0/000987.mp3 renamed as ./testdir/0/987.mp3
and ./testdir/007/00123.mp3 renamed as ./testdir/007/123.mp3
were the results. I think greedy matching of 0*
does the trick.
He also suggested in the comments adding [^/]
in filename pattern matching. This is a good idea since Unix filenames cannot have backslashes in them; paths can but not individual files. However, I am not quite sure how to better implement this and still have no suggestion on matching 0.mp3
or 000.mp3
types of filenames.
Since your question is tagged Linux, you could use rename
or prename
command (note that prename
is not deprecated, though, but still works). In either case they're perl script for pattern-based renaming.
With group matching and using *.mp3
glob to pass only .mp3
files, you can do this:
$ prename -nv 's/(^0*)(.*).mp3/$2.mp3/' *.mp3
Deprecated program in use: rename as shipped with the Debian perl package will be removed after the release of stretch. Please install the separate 'rename' package which will provide the same command.
000004500.mp3 renamed as 4500.mp3
00123.mp3 renamed as 123.mp3
00133.mp3 renamed as 133.mp3
00150.mp3 renamed as 150.mp3
Note that -n
and -v
are for dry run and verbose output; testing only. Remove -n
for actual renaming to take effect.
In case you are confused about rename
vs prename
, you can read the corresponding answer that clears up the confusion, but...I would recommend that you just don't bother with that. Too convoluted :) The point is that in either case it works as shown, unless you're using ksh
shell.
Recursive way to rename files in subfolders would be via find
, however that requires a bit of acrobatics with substitution pattern to handle preceding items in the file path as provided by find
.
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ;
The above command performed as follows in a test case:
$ find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(/0*)(.*).mp3/$1/$3.mp3/' ; 2>/dev/null
./testdir/000004500.mp3 renamed as ./testdir/4500.mp3
./testdir/00150.mp3 renamed as ./testdir/150.mp3
./testdir/00133.mp3 renamed as ./testdir/133.mp3
./testdir/00123.mp3 renamed as ./testdir/123.mp3
Minor improvement could be to specify d
, the digit class:
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's//0*(d*.mp3)//$1/' ;
Stéphane Chazelas mentioned in the comments possibility where /0/1.mp3
could be accidentally rename to .//1.mp3
. I've taken couple test cases; ./testdir/0/000987.mp3 renamed as ./testdir/0/987.mp3
and ./testdir/007/00123.mp3 renamed as ./testdir/007/123.mp3
were the results. I think greedy matching of 0*
does the trick.
He also suggested in the comments adding [^/]
in filename pattern matching. This is a good idea since Unix filenames cannot have backslashes in them; paths can but not individual files. However, I am not quite sure how to better implement this and still have no suggestion on matching 0.mp3
or 000.mp3
types of filenames.
edited Feb 8 at 3:16
answered Feb 7 at 20:51
Sergiy Kolodyazhnyy
7,63311547
7,63311547
The recursive one won't work because^0
will never match because the paths start with./
.
â Stéphane Chazelas
Feb 8 at 0:12
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
There's a risk it could rename things like./0/1.mp3
to.//1.mp3
(or./0.mp3
to./mp3
, see my answer). You may want something likes/0*([0-9][^/]*.mp3)z$2
(untested)
â Stéphane Chazelas
Feb 8 at 0:29
The greedy.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using-execdir
instead of-exec
.
â ilkkachu
Feb 8 at 8:46
add a comment |Â
The recursive one won't work because^0
will never match because the paths start with./
.
â Stéphane Chazelas
Feb 8 at 0:12
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
There's a risk it could rename things like./0/1.mp3
to.//1.mp3
(or./0.mp3
to./mp3
, see my answer). You may want something likes/0*([0-9][^/]*.mp3)z$2
(untested)
â Stéphane Chazelas
Feb 8 at 0:29
The greedy.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using-execdir
instead of-exec
.
â ilkkachu
Feb 8 at 8:46
The recursive one won't work because
^0
will never match because the paths start with ./
.â Stéphane Chazelas
Feb 8 at 0:12
The recursive one won't work because
^0
will never match because the paths start with ./
.â Stéphane Chazelas
Feb 8 at 0:12
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Thank you, I entirely forgot about that. Will try to correct it
â Sergiy Kolodyazhnyy
Feb 8 at 0:16
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
@StéphaneChazelas Edited the answer. Please review.
â Sergiy Kolodyazhnyy
Feb 8 at 0:24
There's a risk it could rename things like
./0/1.mp3
to .//1.mp3
(or ./0.mp3
to ./mp3
, see my answer). You may want something like s/0*([0-9][^/]*.mp3)z$2
(untested)â Stéphane Chazelas
Feb 8 at 0:29
There's a risk it could rename things like
./0/1.mp3
to .//1.mp3
(or ./0.mp3
to ./mp3
, see my answer). You may want something like s/0*([0-9][^/]*.mp3)z$2
(untested)â Stéphane Chazelas
Feb 8 at 0:29
The greedy
.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using -execdir
instead of -exec
.â ilkkachu
Feb 8 at 8:46
The greedy
.*
at the start will effectively force a match on the rightmost possible position, without it, it would take the leftmost. But I suppose you could sidestep the whole issue of accidentally matching the path by using -execdir
instead of -exec
.â ilkkachu
Feb 8 at 8:46
add a comment |Â
up vote
1
down vote
With zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '0#(*.mp3)' '$1'
(remove -n
(dry-run) when happy).
The #
glob operator in zsh
is like the *
regular expression operator.
Note that it would rename 0000.mp3
to .mp3
. To avoid that you can change it do:
zmv -n '0#([0-9]*.mp3)' '$1'
Recursively:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2'
To also remove the () @
characters as your example suggests you may want to do:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2//[() @]'
(It would however not remove those characters from file names that don't start with a digit).
add a comment |Â
up vote
1
down vote
With zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '0#(*.mp3)' '$1'
(remove -n
(dry-run) when happy).
The #
glob operator in zsh
is like the *
regular expression operator.
Note that it would rename 0000.mp3
to .mp3
. To avoid that you can change it do:
zmv -n '0#([0-9]*.mp3)' '$1'
Recursively:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2'
To also remove the () @
characters as your example suggests you may want to do:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2//[() @]'
(It would however not remove those characters from file names that don't start with a digit).
add a comment |Â
up vote
1
down vote
up vote
1
down vote
With zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '0#(*.mp3)' '$1'
(remove -n
(dry-run) when happy).
The #
glob operator in zsh
is like the *
regular expression operator.
Note that it would rename 0000.mp3
to .mp3
. To avoid that you can change it do:
zmv -n '0#([0-9]*.mp3)' '$1'
Recursively:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2'
To also remove the () @
characters as your example suggests you may want to do:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2//[() @]'
(It would however not remove those characters from file names that don't start with a digit).
With zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '0#(*.mp3)' '$1'
(remove -n
(dry-run) when happy).
The #
glob operator in zsh
is like the *
regular expression operator.
Note that it would rename 0000.mp3
to .mp3
. To avoid that you can change it do:
zmv -n '0#([0-9]*.mp3)' '$1'
Recursively:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2'
To also remove the () @
characters as your example suggests you may want to do:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2//[() @]'
(It would however not remove those characters from file names that don't start with a digit).
edited Feb 8 at 0:20
answered Feb 8 at 0:08
Stéphane Chazelas
281k53516847
281k53516847
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f422644%2fremove-first-characters-if-its-0-from-all-files%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
2
Which shell are you using? bash with shell option
extglob
enabled supports"$file##+(0)"
to remove a leading sequence of one or more 0s I thinkâ steeldriver
Feb 7 at 21:17
1
Note that it doesn't work in subdirectories because the asterisk wildcard is not recursive - it will always match items in the specified directory only. This is one thing all shells I'm aware of agree on. If you want to go into subdirectories, you need to figure out (and possibly enable) your shell's equivalent of globstar - likely some variation on
**
.â brhfl
Feb 7 at 21:24