View previous topic :: View next topic |
Author |
Message |
FizzyWidget Veteran
Joined: 21 Nov 2008 Posts: 1133 Location: 127.0.0.1
|
Posted: Wed Jan 25, 2012 8:45 am Post subject: Rename files but not extensions? |
|
|
Seeing as I am moving from Windows to Linux, I am trying to remove the spaces and . I have put into filenames and folders, is there a way using bash to change the spaces and .'s to _ but leaving the extensions of the files untouched?
eg
some folder name - some.folder.name = some_folder_name or Some_Folder_Name
some file name.jpg - some.file.name.jpg = some_file_name.jpg _________________ I know 43 ways to kill with a SKITTLE, so taste my rainbow bitch. |
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 11:00 am Post subject: |
|
|
Yes. _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
|
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 11:06 am Post subject: |
|
|
for f in *; do mv "$f" $(echo $f | tr ' ' '_'); done _________________
Quote: | Removed by Chiitoo |
|
|
Back to top |
|
|
FizzyWidget Veteran
Joined: 21 Nov 2008 Posts: 1133 Location: 127.0.0.1
|
Posted: Wed Jan 25, 2012 11:07 am Post subject: |
|
|
Thanks naib
guessing for .'s i would change it to
for f in *; do mv "$f" $(echo $f | tr '.' '_'); done
? _________________ I know 43 ways to kill with a SKITTLE, so taste my rainbow bitch. |
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 11:10 am Post subject: |
|
|
yup, but that could mangle any extension as well. you can make it perserve extesion via a small tweak _________________
Quote: | Removed by Chiitoo |
|
|
Back to top |
|
|
FizzyWidget Veteran
Joined: 21 Nov 2008 Posts: 1133 Location: 127.0.0.1
|
Posted: Wed Jan 25, 2012 11:11 am Post subject: |
|
|
i dont know how to script, only been on linux full time 3 days so far, how would i tweak it to leave extension alone? _________________ I know 43 ways to kill with a SKITTLE, so taste my rainbow bitch. |
|
Back to top |
|
|
frostschutz Advocate
Joined: 22 Feb 2005 Posts: 2977 Location: Germany
|
Posted: Wed Jan 25, 2012 11:22 am Post subject: Re: Rename files but not extensions? |
|
|
Dark Foo wrote: | Seeing as I am moving from Windows to Linux, I am trying to remove the spaces and . |
I don't get it. Linux can handle spaces and dots fine. Why do you want to mangle your filenames? |
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 11:27 am Post subject: |
|
|
Something like this:
Code: | for file in *; do
base=${file%.*} #isolate filename base
ext=${file##*.} #preserve filename extension
base=${base/ /_} #convert spaces to underscore
base=${base/./_} #convert dot to underscore
mv $file $base$ext #rename the file
done |
_________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
Last edited by Bones McCracker on Wed Jan 25, 2012 11:29 am; edited 1 time in total |
|
Back to top |
|
|
John R. Graham Administrator
Joined: 08 Mar 2005 Posts: 10652 Location: Somewhere over Atlanta, Georgia
|
Posted: Wed Jan 25, 2012 11:30 am Post subject: |
|
|
BoneKracker wrote: | Something like this... | So many quoting errors, so little time.
- John _________________ I can confirm that I have received between 0 and 499 National Security Letters. |
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 11:41 am Post subject: |
|
|
John R. Graham wrote: | BoneKracker wrote: | Something like this... | So many quoting errors, so little time.
- John |
I said "something like". I'm not at my linux machine at the moment.
Are they in fact errors (in bash), or just you being obsessive-compulsive? _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
|
|
Back to top |
|
|
John R. Graham Administrator
Joined: 08 Mar 2005 Posts: 10652 Location: Somewhere over Atlanta, Georgia
|
Posted: Wed Jan 25, 2012 11:55 am Post subject: |
|
|
Not bash syntax errors but errors nonetheless. Properly handling file names with spaces in them requires careful attention to quoting.
Now, that obsessive-compulsive question is a whole different issue.
- John _________________ I can confirm that I have received between 0 and 499 National Security Letters. |
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 12:10 pm Post subject: |
|
|
John R. Graham wrote: | Not bash syntax errors but errors nonetheless. Properly handling file names with spaces in them requires careful attention to quoting.
- John |
I don' tthink there are any quoting errors. I think the string substitution won't work, because it will only replace the first character of each type (space or dot). _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
Last edited by Bones McCracker on Wed Jan 25, 2012 12:27 pm; edited 1 time in total |
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 12:25 pm Post subject: |
|
|
well I wouldn't have named a variable "file" this is a bash command.
so for f in *
Also you are missing recreating the extension "." you changed all . to _ so it would have been: "test one.two.txt" ==> "test_one_two_txt"
The main concern would have been quotes around any variable expansion
Code: |
for f in *; do
mv "$f" "$(echo ${f%.*} | tr ". " "_").${f##*.} "
done |
_________________
Quote: | Removed by Chiitoo |
Last edited by Naib on Wed Jan 25, 2012 12:34 pm; edited 1 time in total |
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 12:33 pm Post subject: |
|
|
Naib wrote: | well I wouldn't have named a variable "file" this is a bash command.
so for f in *
The main concern would have been quotes around any variable expansion
Code: |
for f in *; do
base="${f%.*}" #isolate filename base
ext="${f##*.} " #preserve filename extension
base="${base/ /_}" #convert spaces to underscore
base="${base/./_}" #convert dot to underscore
mv "$f" "$base$ext" #rename the file
done |
|
I use file as a variable name frequently, but you're probably right. I probably shouldn't use base either.
Also, as I said above, the character substitution wont' work; it will only convert the first occurrence. It should be (note double slashes in pattern):
Code: | for f in *; do
b=${f%.*}
e=${f##*.}
b=${b// /_}
b=${b//./_}
echo $b.$e
done |
_________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
Last edited by Bones McCracker on Wed Jan 25, 2012 12:35 pm; edited 1 time in total |
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 12:34 pm Post subject: |
|
|
ninja edit with a more compact solution plus an additional error in your "pseudocode" _________________
Quote: | Removed by Chiitoo |
|
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 12:36 pm Post subject: |
|
|
Naib wrote: | ninja edit with a more compact solution plus an additional error in your "pseudocode" |
No, it's not simply a "more compact solution". You missed the primary change. It will no longer only change the first character; it will change them all.
I changed the filenames out of respect for your suggestion.
If the error you were talking about was the lack of a dot in the final filename, before the extension, I fixed that.
Edit: oh, and the final line should be changed back from 'echo' to 'mv $f', after testing. _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
Last edited by Bones McCracker on Wed Jan 25, 2012 12:38 pm; edited 1 time in total |
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 12:38 pm Post subject: |
|
|
wait what? my solution is compact oO and yes it will change all occurrences since that is required (yes you pseudo wouldn't have)
all . and " " changed to "_" with file extension preservation in 1 line
Code: | for f in *; do mv "$f" "$(echo ${f%.*} | tr ". " "_").${f##*.}"; done |
_________________
Quote: | Removed by Chiitoo |
|
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 12:42 pm Post subject: |
|
|
Naib wrote: | wait what? my solution is compact oO
all . and " " changed to "_" with file extension preservation in 1 line
Code: | for f in *; do mv "$f" "$(echo ${f%.*} | tr ". " "_").${f##*.}"; done |
|
Nice and readable too.
He said he wanted to do it in bash. Calling tr is almost like calling sed (it's like two thirds the size of it). _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
|
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 12:47 pm Post subject: |
|
|
well tr is part of coreutils
but in pure bash, you // for all replace would do:
Code: | for f in *; do t="${f// /_}"; mv "$f" "${t//./_}.${f##*.}"; done |
_________________
Quote: | Removed by Chiitoo |
|
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 12:51 pm Post subject: |
|
|
Naib wrote: | wait what? my solution is compact oO and yes it will change all occurrences since that is required (yes you pseudo wouldn't have)
all . and " " changed to "_" with file extension preservation in 1 line
Code: | for f in *; do mv "$f" "$(echo ${f%.*} | tr ". " "_").${f##*.}"; done |
|
No, my solution works (changes all occurrences), and it's entirely in bash, and it's readable.
Code: | for f in *; do
b=${f%.*}
e=${f##*.}
b=${b// /_}
b=${b//./_}
mv $f $b.$e
done |
Also, echoing to a pipe is a sure sign of an amateur. If you're echoing to a pipe, you're doing something wrong. _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
|
|
Back to top |
|
|
John R. Graham Administrator
Joined: 08 Mar 2005 Posts: 10652 Location: Somewhere over Atlanta, Georgia
|
Posted: Wed Jan 25, 2012 12:59 pm Post subject: |
|
|
I stand corrected on the quoting. Didn't know that a variable expansion was treated atomically. However, Code: | ~ $ f="b.c.d.e"
~ $ e=${f##.*}
~ $ echo $e
b.c.d.e | - John _________________ I can confirm that I have received between 0 and 499 National Security Letters. |
|
Back to top |
|
|
Naib Watchman
Joined: 21 May 2004 Posts: 6059 Location: Removed by Neddy
|
Posted: Wed Jan 25, 2012 1:04 pm Post subject: |
|
|
BoneKracker wrote: | Naib wrote: | wait what? my solution is compact oO and yes it will change all occurrences since that is required (yes you pseudo wouldn't have)
all . and " " changed to "_" with file extension preservation in 1 line
Code: | for f in *; do mv "$f" "$(echo ${f%.*} | tr ". " "_").${f##*.}"; done |
|
No, my solution works (changes all occurrences), and it's entirely in bash, and it's readable.
Code: | for f in *; do
b=${f%.*}
e=${f##*.}
b=${b// /_}
b=${b//./_}
mv $f $b.$e
done |
Also, echoing to a pipe is a sure sign of an amateur. If you're echoing to a pipe, you're doing something wrong. |
one could also say liberal use of temporary variables or over reuse to cascade formatting is also a sign of an amateur, read my last on
Code: | for f in *; do t="${f// /_}"; mv "$f" "${t//./_}.${f##*.}"; done |
pure bash, 1 temp, no re-assignment, no pipes _________________
Quote: | Removed by Chiitoo |
|
|
Back to top |
|
|
Bones McCracker Veteran
Joined: 14 Mar 2006 Posts: 1611 Location: U.S.A.
|
Posted: Wed Jan 25, 2012 1:08 pm Post subject: |
|
|
Naib wrote: | BoneKracker wrote: | Naib wrote: | wait what? my solution is compact oO and yes it will change all occurrences since that is required (yes you pseudo wouldn't have)
all . and " " changed to "_" with file extension preservation in 1 line
Code: | for f in *; do mv "$f" "$(echo ${f%.*} | tr ". " "_").${f##*.}"; done |
|
No, my solution works (changes all occurrences), and it's entirely in bash, and it's readable.
Code: | for f in *; do
b=${f%.*}
e=${f##*.}
b=${b// /_}
b=${b//./_}
mv $f $b.$e
done |
Also, echoing to a pipe is a sure sign of an amateur. If you're echoing to a pipe, you're doing something wrong. |
one could also say liberal use of temporary variables or over reuse to cascade formatting is also a sign of an amateur, read my last on
Code: | for f in *; do t="${f// /_}"; mv "$f" "${t//./_}.${f##*.}"; done |
pure bash, 1 temp, no re-assignment, no pipes |
All you did what take mine and compress it to unreadability. But that conciseness would be desirable if somebody was trying to use 'find' to do this (like if the files were scattered all over the disk) with an -exec and shell command. _________________
patrix_neo wrote: | The human thought: I cannot win.
The ratbrain in me : I can only go forward and that's it. |
|
|
Back to top |
|
|
FizzyWidget Veteran
Joined: 21 Nov 2008 Posts: 1133 Location: 127.0.0.1
|
Posted: Wed Jan 25, 2012 2:20 pm Post subject: |
|
|
Yes i will be using bash, is there another shell that i should be using? Only using that one because i followed the handbook, which ever is suggested i can use _________________ I know 43 ways to kill with a SKITTLE, so taste my rainbow bitch. |
|
Back to top |
|
|
RazielFMX l33t
Joined: 23 Apr 2005 Posts: 835 Location: NY, USA
|
Posted: Wed Jan 25, 2012 2:43 pm Post subject: |
|
|
1) Copy and paste the following into a file, say ~/stripSpaces.pl
Code: | #!/usr/bin/perl -w
use strict;
use Cwd qw(getcwd);
use File::Copy qw(move);
my $dir = getcwd();
opendir(DIR, $dir) or die $!;
my $exitCode = 0;
while (my $file = readdir(DIR)) {
next if ($file !~ /\s+/o); # Don't bother with things that lack spaces
my $new;
if ($file =~ /^(.+)\.(\S+)$/o) {
my $base = $1;
my $ext = $2;
$base =~ s/\s/_/go;
$new = join('.', $base, $ext);
} else {
($new = $file) =~ s/\s/_/go;
}
print STDERR "[INFO] Renaming '$file' to '$new'\n";
my $check = move($file, $new);
if (! $check) {
print STDERR "[WARN] Unable to rename '$file' to '$new': $!\n";
# File::Copy::Move can leave artifacts on the FS
if (-e $new) {
unlink $new;
}
$exitCode = -1 if ($exitCode == 0);
}
}
closedir(DIR);
exit($exitCode); |
2) chmod it: chmod 755 ~/stripSpaces.pl
3) Run it in the directory you want to. |
|
Back to top |
|
|
|