2

If the arguments are files, I want to change their extensions to .file.

That's what I got:

#!/bin/bash

while [ $# -gt 0 ]
do
    if [ -f $1 ]
    then
       sed -i -e "s/\(.*\)\(\.\)\(.*\)/\1\2file" $1

    fi
    shift
done

The script is running, but it doesn't do anything. Another problem is that file hasn't any extension, my sed command will not work, right? Please help.

Eduard Adrian
  • 95
  • 1
  • 12
  • If anything, sed is meant to change the contents of files, not their names. You can use it for the latter, but it's hardly the best tool for it. Your sed command doesn't say what sed should even act on, I supposed your script just hangs on that line, right? – Benjamin W. Jun 18 '17 at 22:54
  • yes,i forgot a $1 after the sed command when i asked the question. but it is not working anyway. – Eduard Adrian Jun 18 '17 at 22:57
  • Yes, because that command changes the *contents* of the files, not their names. – Benjamin W. Jun 18 '17 at 22:58
  • Also, i tried a : $1 mv $1.file but it gives me file.txt.file – Eduard Adrian Jun 18 '17 at 22:58

2 Answers2

3

sed is for manipulating the contents of files, not the filename itself.

Option 1, taken from this answer by John Smith:

filename="file.ext1"
mv "${filename}" "${filename/%ext1/ext2}"

Option 2, taken from this answer by chooban:

rename 's/\.ext/\.newext/' ./*.ext

Option 3, taken from this answer by David W.:

$ find . -name "*.ext1" -print0 | while read -d $'\0' file
do
   mv $file "${file%.*}.ext2"
done

and more is here.

UPDATE : (in comment asked what % and {} doing?)

"${variable}othter_chars" > if you want expand a variable in string you can use it. and %.* in {} means take the value of variable strip off the pattern .* from the tail of the value for example if your variable be filename.txt "${variable%.*} return just filename.

Mr.Sun
  • 129
  • 4
  • The extension of the file is not given. It can be .txt or .file or anything. I want the script to not care about that. – Eduard Adrian Jun 18 '17 at 23:05
  • that's not so big deal man you can in option 3 relpace `"*.ext1"` with `"*.*"` to get any filename with any extention. – Mr.Sun Jun 18 '17 at 23:20
  • Ty,man. It's working. Can you tell me,please what % and {} doing? it's the first time when i`m using them. – Eduard Adrian Jun 18 '17 at 23:35
  • I've edited the answer to reflect more clearly that all solutions are taken from existing answers. If you feel an existing answer is the exact solution to a new question, you should not answer the new question, but mark it as a duplicate of the old one. – Benjamin W. Jun 19 '17 at 00:38
  • @Benjamin Thanks and sorry for i'm not mentioned orginal answer. – Mr.Sun Jun 19 '17 at 11:26
  • 1
    @EduardAdrian i update the answer for your question i hope it help you. – Mr.Sun Jun 19 '17 at 11:27
1

Using a shell function to wrap a sed evaluate (e) command:

mvext () 
{ 
    ext="$1";
    while shift && [ "$1" ]; do
        sed 's/.*/mv -iv "&" "&/
             s/\(.*\)\.[^.]*$/\1/
             s/.*/&\.'"${ext}"'"/e' <<< "$1";
    done
}

Tests, given files bah and boo, and the extension should be .file, which is then changed to .buzz:

 mvext file bah boo
 mvext buzz b*.file

Output:

'bah' -> 'bah.file'
'boo' -> 'boo.file'
'bah.file' -> 'bah.buzz'
'boo.file' -> 'boo.buzz'

How it works:

  1. The first arg is the file extension, which is stored in $ext.
  2. The while loop parses each file name separately, since a name might include escaped spaces and whatnot. If the filenames were certain to have not such escaped spaces, the while loop could probably be avoided.
  3. sed reads standard input, provided by a bash here string <<< "$1".
  4. The sed code changes each name foo.bar (or even just plain foo) to the string "mv -iv foo.bar foo.file" then runs that string with the evaluate command. The -iv options show what's been moved and prompts if an existing file might be overwritten.
agc
  • 7,973
  • 2
  • 29
  • 50