简体   繁体   中英

Changing file extension in bash

Hello i have to change file extension, but i must type it when i call script

so i trying

 #!/bin/bash
echo "Hello "
roz1="$1"
roz2="$2"
katalog="$3" 
for i in `find . -name '*$roz1'`
do 
tmp=`basename $i $roz1t`
mv "${tmp}$roz1" "${tmp}$roz2"
done 

And i type /.script .txt .html When i change it to this

#!/bin/bash
echo "Hello "
roz1="$1"
roz2="$2"
katalog="$3" 
for i in `find . -name '*.txt'`
do 
tmp=`basename $i .txt`
mv "${tmp}.txt" "${tmp}.html"
done

All working file, i known it is bad variables $1 $2 call , but i can't fix it.

There are several quick and easy ways to approach this problem. Following from your attempt, we take the current and new extensions from the command line. You then need to validate 2 inputs and then remove the leading '.' if any from the front of each extension in order to be able to consistently handle user input with or without a leading dot.

Then it is a simple matter of selecting the files by extension, and move while removing the unwanted extension and appending the new one. That can take place all in one call using substring extraction:

#!/bin/bash

[ -z $1 -o -z $2 ] && {  ## validate both extensions given
    printf "error: insufficient input. usage: %s ext1 ext2\n" "${0//*\//}"
    exit 1
}

ext1="$1"  ## assign input to variables
ext2="$2"

## remove leading '.' if it exists
#  allows handling with/without '.'
[ ${ext1:0:1} = . ] && ext1=${ext1:1}
[ ${ext2:0:1} = . ] && ext2=${ext2:1}

## read each file in list
while read -r fname; do

    ## simple move from ext1 to ext2 using substring extraction
    mv "$fname" "${fname%.$ext1}.$ext2"

done < <(find . -type f -name "*.$ext1")

exit 0

Explanation

${var#expression} or ${var%expression} relies on parameter expansion/substring removal . Those are the two basic forms. The first with # says remove the first occurrence of what is in expression from $var starting from the LEFT . The % variant starts from the RIGHT . Using ## or %% says remove all occurrences of expression in $var . So "${fname%.$ext1}.$ext2" says remove the contents of $ext1 (the first extension) from the full filename $fname (from the right -- leaving only the filename without an extension) and then tack .$ext2 (the new extension) on to the end (creating your new file name). Example:

$ a=file.txt; echo ${a%.txt}; echo ${a%.txt}.html
file
file.html

The ${ext1:0:1} type are simple string index expressions. They are ${var:start:length} (where if no length , the default is from start to end of string ). So ext1=${ext1:1} just says skip the 1st char and copy remainder. (basically drop the first char if it was a '.' ). You can also index from the end, but the syntax is special. To index from the end, you use ${var: -4:1} ( note the space between : -4 ) or you can use parenthesis ${var:(-4):1} . Both start 4 chars from the end and get 1 char (eg the . in file.txt ). Example:

$ a=file.txt; b=file.txt; echo ${a: -4:1}; echo ${b:(-4):1}
.
.

Test Files for the full script

$  ls -1
chext.sh
file1.txt
file2.txt
file3.txt
file4.txt
file5.txt

Use/Result

Changing .txt extensions to .html:

$ bash chext.sh txt html

$ ls -1
chext.sh
file1.html
file2.html
file3.html
file4.html
file5.html

You should read about Quoting .
find . -name '*$roz1' find . -name '*$roz1' will actually match literal $roz1, it will not be expanded.

You should use double quotes like find . -name "*$roz" find . -name "*$roz"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM