LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Clueless on how to remove spaces from all .jpg's beneath a folder (https://www.linuxquestions.org/questions/linux-newbie-8/clueless-on-how-to-remove-spaces-from-all-jpgs-beneath-a-folder-754164/)

anon091 09-10-2009 09:38 AM

Clueless on how to remove spaces from all .jpg's beneath a folder
 
OK, I have a folder, that has multiple subfolders (which have subfolders of their own) containing a variety of different files. What I need to do is remove all the spaces from the filenames of .jpg files only in all those folders.

Please tell me there is a way to do this with some fancy command way above my skillset.

catkin 09-10-2009 09:52 AM

Quote:

Originally Posted by rjo98 (Post 3677344)
OK, I have a folder, that has multiple subfolders (which have subfolders of their own) containing a variety of different files. What I need to do is remove all the spaces from the filenames of .jpg files only in all those folders.

Please tell me there is a way to do this with some fancy command way above my skillset.

There is a way to do this with some fancy command!

Create a myscript.sh
Code:

#!/bin/bash
for file in "$@"
do
    newfilename="${file// /}"
    if [[ "$newfilename" != "$file" ]]; then
      echo mv "$file" "$newfilename"
    fi
done

Make it executable with chmod +x myscript.sh

Now run
Code:

find <my folder> -iname '*.jpg' -exec <full path to myscript.sh> {} +
When you are happy that all the commands echoed are what you want to execute then remove "echo" from myscript.sh and run the find command again.

i92guboj 09-10-2009 09:52 AM

Remove or substitute by _ or something else?

You could use find.

Code:

find . -type f -name '* *'.[jJ][pP][gG] | while read file; do mv "$file" "${file// /}"; done
# or
find . -type f -name '* *'.[jJ][pP][gG] | while read file; do mv "$file" "${file// /_}"; done


anon091 09-10-2009 10:03 AM

thanks guys. i92, that looks similar to something i've seen someone else do before, so i might go with that. I'd just like to remove the spaces, don't need to substitute an underscore. so do i just use the top line of your last post? can you explain what the part after "do" does, i'm confused.

malekmustaq 09-10-2009 10:03 AM

rj098,

if you want to do it in auto fashion you will need a script and run it.
certainly this requires workable knowledge of bash scripting.
you can get similar script here click this. Or click this it will also give you another idea.

there is a good scripting guide click here.

hope it helps.

good luck.

i92guboj 09-10-2009 10:11 AM

Quote:

Originally Posted by rjo98 (Post 3677384)
thanks guys. i92, that looks similar to something i've seen someone else do before, so i might go with that. I'd just like to remove the spaces, don't need to substitute an underscore. so do i just use the top line of your last post?

Yes. But use this one instead:

Code:

find . -type f -name '* *'.[jJ][pP][gG] | while read file; do echo mv "$file" "${file// /}"; done
That will list the list of commands that will be run. If you like the results, then remove "echo" from the command and run it again to do the real work.

Quote:

can you explain what the part after "do" does, i'm confused.
find will generate a list of files that contains at least a space on their name, and whose extension is jpg, JPG, Jpg or some other combo with that letters. "while" will consume it, one item at a time, assigning a new file name on each loop to $file. On each loop, the command "mv" is run, and it moves the file pointed by $file to it's new name.

The part that is less clear to you is probably this:

Code:

"${file// /}"
This is a feature of the bash shell (meaning that other shells don't have it). Bash has some basic string processing capabilities. In this case, we use this to substitute all occurrences of " " (blank space) by "" (nothing). The syntax is this:

Code:

${variable//substring_to_substitute/new_substring}
That results in a string that's very similar to the original file name, but doesn't contain any space, since all the blanks have been substituted by "". There's a similar form which will only substitute the first instance of the substring:

Code:

${variable/substring_to_substitute/new_substring}
You might want to check this article (and the responses which expand it):

http://www.linuxjournal.com/article/8919

There is much more about this in the bash manual page, look for the section called "EXPANSION".

vonbiber 09-10-2009 10:12 AM

Quote:

Originally Posted by rjo98 (Post 3677344)
OK, I have a folder, that has multiple subfolders (which have subfolders of their own) containing a variety of different files. What I need to do is remove all the spaces from the filenames of .jpg files only in all those folders.

1. copy and paste the shell script below
2. replace 'absolute_path_to_the_top_directory' by the
absolute path to your top folder
3. save and make the shell script executable,
then run the script
it will just echo what it's doing. If it looks ok you can
run it for real by uncommenting the line
# mv "$f" "$nf"
and removing this line
echo "mv \"$f\" \"$nf\""

I assume you have write permission in those folders

Code:

##### copy and paste below this line #####
#!/bin/sh

TOP=absolute_path_to_the_top_directory

if [ ! -d $TOP ]; then
        echo "sorry $TOP doesn't exist or is not a directory"
        exit 1
fi

find $TOP/* | while read f
do
        if [ -d $f ]; then
                continue
        fi
        g="${f##*/}"
        ext="${g##*.}"
        if [ $(echo $ext | tr '[:upper:]' '[:lower:]') == jpg ]; then
                ng="$(echo $g | sed 's? \{1,\}??g')"
                nf="${f%/*}/$ng"
                if [ "$nf" != "$f" ]; then
#                      mv "$f" "$nf"
                        echo "mv \"$f\" \"$nf\""
                fi
        fi
done
##### end of copy above this line


catkin 09-10-2009 10:18 AM

Quote:

Originally Posted by i92guboj (Post 3677404)
Yes. But use this one instead:

Code:

find . -name '* *'.[jJ[pP][gG] | while read file; do echo mv "$file" "${file// /}"; done

Neat! :)

A closing bracket missing though
Code:

find . -name '* *'.[jJ][pP][gG] | while read file; do echo mv "$file" "${file// /}"; done

i92guboj 09-10-2009 10:25 AM

Good catch, catkin ;)

/me goes fixing posts above yet again :p

anon091 09-10-2009 11:09 AM

Very cool! i like that it gets all occurances and not just the first occurance of a space. Thanks to everybody, this is going to help me out BIG TIME.

anon091 09-10-2009 11:16 AM

so where you have the . at the beginning of the line, i should put in my full path to the root folder of where i want the magic to happen, or should i just cd /full/path then run it exactly as you have it written?

i92guboj 09-10-2009 11:21 AM

Either way will work, anyway, until you remove the "echo" it's safe to run it, and you can see what will it do. You could as well use a relative path (in fact, "." itself is a relative path).

ps. When running interactively I preffer to cd to the dir, because that way the paths are shorter and the output is less confusing, but besides that it's a merely cosmetic thing.

anon091 09-10-2009 11:23 AM

ok, thanks, i'll probably just cd to the folder i want it to start at and run it with the . then

many thanks to everyone!

anon091 09-10-2009 11:26 AM

CORRECT>find . -name '* *'.[jJ][pP][gG] | while read file; od echo mv "$file" "${file// /}"; done (y|n|e|a)?


it said that when i typed in the command, do i just type y and let it rip?

i92guboj 09-10-2009 11:31 AM

Quote:

Originally Posted by rjo98 (Post 3677496)
CORRECT>find . -name '* *'.[jJ][pP][gG] | while read file; od echo mv "$file" "${file// /}"; done (y|n|e|a)?


it said that when i typed in the command, do i just type y and let it rip?

It shouldn't ask you anything, if should either work or fail. Maybe you are using a different shell. Can you post the output of this command?

Code:

echo $0
By the way, there's a typo in the command above. It's "do" instead of "od".


All times are GMT -5. The time now is 02:43 PM.