You are not logged in.
Renaming files using sed is nothing new, but this script makes the process a little more friendly and adds a few features, including insertion of sequential numbers and a simulation mode. The output of any find command can also be piped through sedname.
sedname version 1.0.0
Batch-renames files using a sed script
Usage: sedname [OPTIONS] SEDSCRIPT FILE ...
Usage: find [...] | sedname [OPTIONS] SEDSCRIPT
Example: sedname 's/\(.*\)\.jpg/\1.jpeg/' *.jpg
Example: find /mypics | sedname 's/\(.*\)\.jpg/\1.jpeg/'
OPTIONS:
--sim simulate only
--dir rename directories too
Use #D to insert a number with D digits forming a unique filename
Example: sedname 's/thisname.*/thatname#3/' *
( changes thisname* to thatname001, thatname002, ... )
Use #0 in replacement name to insert a number if needed
Example: sedname 's/thisname.*/thatname#0/' *
( changes thisname* to thatname, thatname1, thatname2, ... )
http://igurublog.wordpress.com/download … t-sedname/
http://aur.archlinux.org/packages.php?ID=37707
Offline
You know of prename, right?
Offline
prename, and also mmv (iirc) and rename have the problem of trying to rename the directory. E.g. rename 'e' 'e1' /home/user/file.txt -> /home1/user/file.txt, while you obviously wanted a file1.txt
This one seems quite a bit nicer.
Offline
What does it have over zsh's zmv:
# Remove illegal characters in a fat32 file system. Illegal characters are
# / : ; * ? " < > |
# NOTE: ``-Q'' and (D) is to include hidden files.
$ unwanted='[:;*?\"<>|]'
$ zmv -Q "(**/)(*$~unwanted*)(D)" '$1${2//$~unwanted/}'
# Changing part of a filename (i. e. "file-hell.name" -> "file-heaven.name")
$ zmv '(*)hell(*)' '${1}heaven${2}'
# or
$ zmv '*' '$f:s/hell/heaven/'
# remove round bracket within filenames
# i. e. foo-(bar).avi -> foo-bar.avi
$ zmv '*' '${f//[()]/}'
# serially all files (foo.foo > 1.foo, fnord.foo > 2.foo, ..)
$ ls *
1.c asd.foo bla.foo fnord.foo foo.fnord foo.foo
$ c=1 zmv '*.foo' '$((c++)).foo'
$ ls *
1.c 1.foo 2.foo 3.foo 4.foo foo.fnord
# Rename "file.with.many.dots.txt" by substituting dots (exept for the last
# one!) with a space
$ touch {1..20}-file.with.many.dots.txt
$ zmv '(*.*)(.*)' '${1//./ }$2'
# Remove the first 4 chars from a filename
$ zmv -n '*' '$f[5,-1]' # NOTE: The "5" is NOT a mistake in writing!
# Rename names of all files under the current Dir to lower case, but keep
# dirnames as-is.
$ zmv -Qv '(**/)(*)(.D)' '$1${(L)2}'
# replace all 4th character, which is "1", with "2" and so on
$ zmv '(???)1(???[1-4].txt)' '${1}2${2}'
# Remove the first 15 characters from a string
$ touch 111111111111111{a-z}
$ zmv '*' '$f[16,-1]'
# Replace spaces (any number of them) with a single dash in file names
$ zmv -n '(**/)(* *)' '$1${2//( #-## #| ##)/-}'
# or - with Bash
$ find . -depth -name '* *' -exec bash -c '
> shopt -s extglob
> file=$1
> dir=${file%/*}
> name=${file##*/}
> newname=${name//*([ -]) *([ -])/-}
> mv -i -- "$file" "$Dir/$newname"' {} {} \;
# Clean up file names and remove special characters
$ zmv -n '(**/)(*)' '$1${2//[^A-Za-z0-9._]/_}'
# Add *.py to a bunch of python scripts in a directory (some of them end
# in *.py and give them all a proper extension
$ zmv -n '(**/)(con*)(#qe,file $REPLY | grep "python script",)' '$1$2.py'
# lowercase all extensions (i. e. *.JPG) incl. subfolders
$ zmv '(**/)(*).(#i)jpg' '$1$2.jpg'
# Or - without Zsh
$ find Dir -name '*.[jJ][pP][gG]' -print | while read f
> do
> case $f in
> *.jpg) ;
> *) mv "$f" "${f%.*}.jpg" ;
> esac
> done
# remove leading zeros from file extension
$ ls
filename.001 filename.003 filename.005 filename.007 filename.009
filename.002 filename.004 filename.006 filename.008 filename.010
$ zmv '(filename.)0##(?*)' '$1$2'
$ ls
filename.1 filename.10 filename.2 filename.3 filename.4 filename.5 ..
# renumber files.
$ ls *
foo_10.jpg foo_2.jpg foo_3.jpg foo_4.jpg foo_5.jpg foo_6.jpg ..
$ zmv -fQ 'foo_(<0->).jpg(.nOn)' 'foo_$(($1 + 1)).jpg'
$ ls *
foo_10.jpg foo_11.jpg foo_3.jpg foo_4.jpg foo_5.jpg ...
# adding leading zeros to a filename (1.jpg -> 001.jpg, ..
$ zmv '(<1->).jpg' '${(l:3::0:)1}.jpg'
# See above, but now only files with a filename >= 30 chars
$ c=1 zmv "${(l:30-4::?:)}*.foo" '$((c++)).foo'
# Replace spaces in filenames with a underline
$ zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
$ zmv -W '*.sh' '*.pl'
# Add a "".txt" extension to all the files within ${HOME}
# ``-.'' is to only rename regular files or symlinks to regular files,
# ``D'' is to also rename hidden files (dotfiles))
$ zmv -Q '/home/**/*(D-.)' '$f.txt'
# Or to only rename files that don't have an extension:
$ zmv -Q '/home/**/^?*.*(D-.)' '$f.txt'
# Recursively change filenames with characters ? [ ] / = + < > ; : " , - *
$ chars='[][?=+<>;",*-]'
$ zmv '(**/)(*)' '$1${2//$~chars/%}'
# Removing single quote from filenames (recursively)
$ zmv -Q "(**/)(*'*)(D)" "\$1\${2//'/}"
# When a new file arrives (named file.txt) rename all files in order to
# get (e. g. file119.txt becomes file120.txt, file118.txt becomes
# file119.txt and so on ending with file.txt becoming file1.txt
$ zmv -fQ 'file([0-9]##).txt(On)' 'file$(($1 + 1)).txt'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase
# Remove the suffix *.c from all C-Files
$ zmv '(*).c' '$1'
# Uppercase only the first letter of all *.mp3 - files
$ zmv '([a-z])(*).mp3' '${(C)1}$2.mp3'
# Copy the target `README' in same directory as each `Makefile'
$ zmv -C '(**/)Makefile' '${1}README'
# Removing single quote from filenames (recursively)
$ zmv -Q "(**/)(*'*)(D)" "\$1\${2//'/}"
# Rename pic1.jpg, pic2.jpg, .. to pic0001.jpg, pic0002.jpg, ..
$ zmv 'pic(*).jpg' 'pic${(l:4::0:)1}.jpg'
$ zmv '(**/)pic(*).jpg' '$1/pic${(l:4::0:)2}.jpg' # recursively
(from zsh-lovers)
Edit: tried it now, and had to remove this silly block to make it let me use alternate delimiters:
if [ "${sedscript:0:2}" != "s/" ]; then
echo "Invalid sed script: $sedscript" > /dev/stderr
exit 1
fi
Last edited by JohannesSM64 (2010-05-31 15:29:44)
Offline
What does it have over zsh's zmv:
Well like I said, renaming with sed, and sed-like tools, is nothing new. I'm not familiar with zmv and it does look like a capable tool, but looking it over it seems to use a different script syntax. One advantage of sedname is that if you're used to using sed, you know the usage already. Also, the ability to pipe find's output directly through sedname creates very flexible usage, and again is something that people are already more familiar with. And I like a simulation mode, especially for those less familiar with sed. Since there is no way to un-rename it's good to be able to see what your command will do before committing changes.
Anyway sedname is not a complex or large script - it just creates an easy-to-use bridge between common tools. It was my particular solution to the problem.
Offline
Edit: tried it now, and had to remove this silly block to make it let me use alternate delimiters:
I agree - I'm going to take that out. I originally put that in because I wanted it smart enough to recognize a sed script so it could advise inexperienced users on what was missing, but I don't want to limit sed's usage.
Edit: that test has been removed in 1.0.1
Last edited by IgnorantGuru (2010-05-31 16:01:12)
Offline
It's indeed a nice script now Thanks for the contribution.
Offline
Thanks for your feedback.
Offline