开发者

Recursive BASH renaming

EDIT: Ok, I'm sorry, I should have specified that I was on Windows, and using win-bash, which is based on bash 1.14.2, along with the gnuwin32 tools. This means all of the solutions posted unfortunately didn't help out. It doesn't contain many of the advanced features. I have however figured it out finally. It's an ugly script, but it works.

#/bin/bash
function readdir
{
  cd "$1"
  for infile in *
  do
    if [ -d "$infile" ]; then
      readdir "$infile"
    else
      renamer "$infile"
    fi
  done
  cd ..
}

function renamer
{
  #replace " - " with a si开发者_运维百科ngle underscore.
  NEWFILE1=`echo "$1" | sed 's/\s-\s/_/g'`
  #replace spaces with underscores
  NEWFILE2=`echo "$NEWFILE1" | sed 's/\s/_/g'`
  #replace "-" dashes with underscores.
  NEWFILE3=`echo "$NEWFILE2" | sed 's/-/_/g'`
  #remove exclamation points
  NEWFILE4=`echo "$NEWFILE3" | sed 's/!//g'`
  #remove commas
  NEWFILE5=`echo "$NEWFILE4" | sed 's/,//g'`
  #remove single quotes
  NEWFILE6=`echo "$NEWFILE5" | sed "s/'//g"`
  #replace & with _and_
  NEWFILE7=`echo "$NEWFILE6" | sed "s/&/_and_/g"`
  #remove single quotes
  NEWFILE8=`echo "$NEWFILE7" | sed "s/’//g"`

  mv "$1" "$NEWFILE8"
}

for infile in *
do
  if [ -d "$infile" ]; then
    readdir "$infile"
  else
    renamer "$infile"
  fi
done

ls

I'm trying to create a bash script to recurse through a directory and rename files, to remove spaces, dashes and other characters. I've gotten the script working fine for what I need, except for the recursive part of it. I'm still new to this, so it's not as efficient as it should be, but it works. Anyone know how to make this recursive?

#/bin/bash
for infile in *.*;
do 
#replace " - " with a single underscore.
NEWFILE1=`echo $infile | sed 's/\s-\s/_/g'`; 
#replace spaces with underscores
NEWFILE2=`echo $NEWFILE1 | sed 's/\s/_/g'`; 
#replace "-" dashes with underscores.
NEWFILE3=`echo $NEWFILE2 | sed 's/-/_/g'`; 
#remove exclamation points
NEWFILE4=`echo $NEWFILE3 | sed 's/!//g'`; 
#remove commas
NEWFILE5=`echo $NEWFILE4 | sed 's/,//g'`; 
mv "$infile" "$NEWFILE5";
done;


find is the command able to display all elements in a filesystem hierarchy. You can use it to execute a command on every found file or pipe the results to xargs which will handle the execution part.

Take care that for infile in *.* does not work on files containing whitespaces. Check the -print0 option of find, coupled to the -0 option of xargs.


All those semicolons are superfluous and there's no reason to use all those variables. If you want to put the sed commands on separate lines and intersperse detailed comments you can still do that.

#/bin/bash
find . | while read -r file
do
    newfile=$(echo "$file" | sed '
        #replace " - " with a single underscore.
        s/\s-\s/_/g 
        #replace spaces with underscores
        s/\s/_/g
        #replace "-" dashes with underscores.
        s/-/_/g
        #remove exclamation points
        s/!//g
        #remove commas
        s/,//g')
    mv "$infile" "$newfile"
done

This is much shorter:

#/bin/bash
find . | while read -r file
do
    # replace " - " or space or dash with underscores
    # remove exclamation points and commas
    newfile=$(echo "$file" | sed 's/\s-\s/_/g; s/\s/_/g; s/-/_/g; s/!//g; s/,//g')
    mv "$infile" "$newfile"
done

Shorter still:

#/bin/bash
find . | while read -r file
do
    # replace " - " or space or dash with underscores
    # remove exclamation points and commas
    newfile=$(echo "$file" | sed 's/\s-\s/_/g; s/[-\s]/_/g; s/[!,]//g')
    mv "$infile" "$newfile"
done


In bash 4, setting the globstar option allows recursive globbing.

shopt -s globstar
for infile in **
 ...

Otherwise, use find.

while read infile
do
 ...
done < <(find ...)

or

find ... -exec ...


I've used 'find' in the past to locate files then had it execute another application. See '-exec'


rename 's/pattern/replacement/' glob_pattern
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜