Rename file names in current directory and all sub

2019-08-14 17:18发布

问题:

I have 4 files with the following names in different directories and subdirectories

tag0.txt, tag1.txt, tag2.txt and tag3.txt 

and wish to rename them as tag0a.txt, tag1a.txt ,tag2a.txt and tag3a.txt in all directories and subdirectories.

Could anyone help me out using a shell script?

Cheers

回答1:

$ shopt -s globstar
$ rename -n 's/\.txt$/a\.txt/' **/*.txt
foo/bar/tag2.txt renamed as foo/bar/tag2a.txt
foo/tag1.txt renamed as foo/tag1a.txt
tag0.txt renamed as tag0a.txt

Remove -n to rename after checking the result - It is the "dry run" option.



回答2:

This can of course be done with find:

find . -name 'tag?.txt' -type f -exec bash -c 'mv "$1" ${1%.*}a.${1##*.}' -- {} \;


回答3:

Here is a posix shell script (checked with dash):

visitDir() {
    local file
    for file in "$1"/*; do
            if [ -d "$file" ]; then
                    visitDir "$file";
            else
                    if [ -f "$file" ] && echo "$file"|grep -q '^.*/tag[0-3]\.txt$'; then
                            newfile=$(echo $file | sed 's/\.txt/a.txt/')
                            echo mv "$file" "$newfile"
                    fi
            fi

    done
}

visitDir .

If you can use bashisms, just replace the inner IF with:

if [[ -f "$file" && "$file" =~ ^.*/tag[0-3]\.txt$ ]]; then
    echo mv "$file" "${file/.txt/a.txt}"
fi

First check that the result is what you expected, then possibly remove the "echo" in front of the mv command.



回答4:

Using the Perl script version of rename that may be on your system:

find . -name 'tag?.txt' -exec rename 's/\.txt$/a$&/' {} \;

Using the binary executable version of rename:

find . -name 'tag?.txt' -exec rename .txt a.txt {} \;

which changes the first occurrence of ".txt". Since the file names are constrained by the -name argument, that won't be a problem.



回答5:

Is this good enough?


jcomeau@intrepid:/tmp$ find . -name tag?.txt
./a/tag0.txt
./b/tagb.txt
./c/tag1.txt
./c/d/tag3.txt
jcomeau@intrepid:/tmp$ for txtfile in $(find . -name 'tag?.txt'); do \
 mv $txtfile ${txtfile%%.txt}a.txt; done
jcomeau@intrepid:/tmp$ find . -name tag*.txt
./a/tag0a.txt
./b/tagba.txt
./c/d/tag3a.txt
./c/tag1a.txt

Don't actually put the backslash into the command, and if you do, expect a '>' prompt on the next line. I didn't put that into the output to avoid confusion, but I didn't want anybody to have to scroll either.



标签: bash unix shell