0

Trying to remove a string that is located after the file name extension, on multiple files at once. I do not know where the files will be, just that they will reside in a subfolder of the one I am in.

Need to remove the last string, everything after the file extension. File name is:

something-unknown.js?ver=12234.... (last bit is unknown too)

This one (below) I found in this thread:

for nam in *sqlite3_done
do
    newname=${nam%_done}
    mv $nam $newname
done

I know that I have to use % to remove the bit from the end, but how do I use wildcards in the last bit, when I already have it as the "for any file" selector?

Have tried with a modifies bit of the above:

for nam in *.js*
do
    newname=${ nam .js% } // removing all after .js
    mv $nam $newname
done

I´m in MacOS Yosemite, got bash shell and sed. Know of rename and sed, but I´ve seen only topics with specific strings, no wildcards for this issue except these:

How to rename files using wildcard in bash?

https://unix.stackexchange.com/questions/227640/rename-first-part-of-multiple-files-with-mv

andiOak
  • 356
  • 3
  • 9
  • **So, to tie this one off:** Here is my final version of this solution, specifically here for JS files with wordpress type file-url-extensions: `for x in $(find . -type f -name '*.js*');do mv -v $x $(echo $x | sed 's/\.js.*/.js/'); done` and here it is in foo: `for x in $(find . -type f -name '*.foo*');do mv -v $x $(echo $x | sed 's/\.foo.*/.foo/'); done` Note the `-v` I added, for verbose mode. – andiOak Nov 28 '18 at 22:32

2 Answers2

1

I think this is what you are looking for in terms of parameter substitution:

$ ls -C1
first-unknown.js?ver=111
second-unknown.js?ver=222
third-unknown.js?ver=333

$ for f in *.js\?ver=*; do echo ${f%\?*}; done
first-unknown.js
second-unknown.js
third-unknown.js

Note that we escape the ? as \? to say that we want to match the literal question mark, distinguishing it from the special glob symbol that matches any single character.

Renaming the files would then be something like:

$ for f in *.js\?ver=*; do echo "mv $f ${f%\?*}"; done
mv first-unknown.js?ver=111 first-unknown.js
mv second-unknown.js?ver=222 second-unknown.js
mv third-unknown.js?ver=333 third-unknown.js

Personally I like to output the commands, save it to a file, verify it's what I want, and then execute the file as a shell script.

If it needs to be fully automated you can remove the echo and do the mv directly.

jas
  • 10,715
  • 2
  • 30
  • 41
  • 2
    I always recommend using `mv -i` or `-n` when doing mass renames/moves like this, to avoid data loss in case of name conflicts. – Gordon Davisson Nov 27 '18 at 17:51
  • I just verified that this worked! It takes all files in one single folder and renames all past ".js" into only ".js". So "anything-here.js?ver=12345" into "anything-here.js". Thanks. – andiOak Nov 27 '18 at 18:54
0
for x in $(find . -type f -name '*.js*');do mv $x $(echo $x | sed 's/\.js.*/.js/'); done
jas
  • 10,715
  • 2
  • 30
  • 41
Kyle Banerjee
  • 2,554
  • 4
  • 22
  • 30
  • I just verified that this worked as well. It takes all files in the **current folder AND all sub-folders** and removes all strings in file names past "**.js**". So "**anything-here.js?ver=12345**" becomes "**anything-here.js**". Thanks. – andiOak Nov 27 '18 at 18:56
  • Using `sed`, this is the most **efficient** one for me, recursively going through all files in current folder and sub folders. – andiOak Nov 27 '18 at 19:04