You are not logged in.

#1 2010-05-30 22:59:09

IgnorantGuru
Member
Registered: 2009-11-09
Posts: 640
Website

sedname - Batch rename files using sed

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

#2 2010-05-31 03:32:19

dmz
Member
From: Sweden
Registered: 2008-08-27
Posts: 881
Website

Re: sedname - Batch rename files using sed

You know of prename, right? smile

Offline

#3 2010-05-31 03:55:56

Procyon
Member
Registered: 2008-05-07
Posts: 1,819

Re: sedname - Batch rename files using sed

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

#4 2010-05-31 10:33:43

JohannesSM64
Member
From: Norway
Registered: 2009-10-11
Posts: 623
Website

Re: sedname - Batch rename files using sed

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

#5 2010-05-31 15:47:48

IgnorantGuru
Member
Registered: 2009-11-09
Posts: 640
Website

Re: sedname - Batch rename files using sed

JohannesSM64 wrote:

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

#6 2010-05-31 15:49:54

IgnorantGuru
Member
Registered: 2009-11-09
Posts: 640
Website

Re: sedname - Batch rename files using sed

JohannesSM64 wrote:

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

#7 2010-05-31 17:10:09

JohannesSM64
Member
From: Norway
Registered: 2009-10-11
Posts: 623
Website

Re: sedname - Batch rename files using sed

It's indeed a nice script now smile Thanks for the contribution.

Offline

#8 2010-05-31 17:38:12

IgnorantGuru
Member
Registered: 2009-11-09
Posts: 640
Website

Re: sedname - Batch rename files using sed

Thanks for your feedback.

Offline

Board footer

Powered by FluxBB