Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
02-05-2008, 12:53 PM
|
#1
|
|
LQ Newbie
Registered: Dec 2007
Posts: 2
Rep:
|
Remove whitespace in file and directory names using bash
Hello, I am trying to write a very basic shell script to replace white space in file and directory names with underscores. I realize that there are probably several better ways to do this. Here is what I have come up with so far with two small scripts:
wsfind
Code:
#!/bin/bash
directory=$1
find $directory -name '* *' -exec wsrem \"{}\" \;
wsrem
Code:
#!/bin/bash
input=$1
echo $input
files=$(echo $input | tr ' ' _ | tr \" ' ') #replace white space with _ and remove quotes.
echo $files
mv -v $input $files
I have created some test files/directories and here is the output I get:
Code:
root@underwearless:~# wsrem test/
"test/this is a test"
test/this_is_a_test
mv: target `test/this_is_a_test' is not a directory
"test/this is a test/this is a test"
test/this_is_a_test/this_is_a_test
mv: target `test/this_is_a_test/this_is_a_test' is not a directory
"test/fjkd ls"
test/fjkd_ls
mv: target `test/fjkd_ls' is not a directory
Bash seems to be creating the string I want but they aren't be interpreted by mv correctly. Any thought on how to fix what I have or perhaps a better idea on how to implement this?
|
|
|
|
02-05-2008, 02:29 PM
|
#2
|
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,697
|
rename 's/ /_/g' file name
Using the perl rename command.
|
|
|
1 members found this post helpful.
|
02-05-2008, 03:25 PM
|
#3
|
|
Moderator
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,915
|
Quote:
Originally Posted by TheFutonEng
Hello, I am trying to write a very basic shell script to replace white space in file and directory names with underscores. I realize that there are probably several better ways to do this. Here is what I have come up with so far with two small scripts:
wsfind
Code:
#!/bin/bash
directory=$1
find $directory -name '* *' -exec wsrem \"{}\" \;
wsrem
Code:
#!/bin/bash
input=$1
echo $input
files=$(echo $input | tr ' ' _ | tr \" ' ') #replace white space with _ and remove quotes.
echo $files
mv -v $input $files
I have created some test files/directories and here is the output I get:
Code:
root@underwearless:~# wsrem test/
"test/this is a test"
test/this_is_a_test
mv: target `test/this_is_a_test' is not a directory
"test/this is a test/this is a test"
test/this_is_a_test/this_is_a_test
mv: target `test/this_is_a_test/this_is_a_test' is not a directory
"test/fjkd ls"
test/fjkd_ls
mv: target `test/fjkd_ls' is not a directory
Bash seems to be creating the string I want but they aren't be interpreted by mv correctly. Any thought on how to fix what I have or perhaps a better idea on how to implement this?
|
Without having spent too much thought or testing on
it I'd guess that the problem is that you're not
quoting the original string. Bash thinks that you're
trying to move several files (e.g. mv "test/this" "is"
"a" test" test/this_is_a_test) to some other directory
rather than renaming a file. And the target is not (an
existing) directory. If you tried mv -v "$input" "$files"
it should work?
Cheers,
Tink
|
|
|
|
02-05-2008, 05:06 PM
|
#4
|
|
Member
Registered: May 2007
Distribution: Debian
Posts: 754
Rep:
|
Quote:
Originally Posted by David the H.
rename 's/ /_/g' file name
Using the perl rename command.
|
Maybe I'm wrong, but I don't think that what you wrote is functional Perl. Something like this would work though:
Code:
#!/usr/bin/perl
use strict;
use warnings;
foreach my $file (@ARGV) {
(my $new_name = $file) =~ s/ /_/g;
rename $file, $new_name;
}
Whatever files you specify on the command line (and you can use * to mean everything in the current directory that this rule applies to) would have single spaces changed to underscores.
|
|
|
|
02-05-2008, 05:58 PM
|
#5
|
|
Moderator
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,915
|
Quote:
Originally Posted by Telemachos
Maybe I'm wrong, but I don't think that what you wrote is functional Perl.
|
You are wrong ...
rename is a perl-script included in debian based distros,
and the invocation "David the H" was using is perfectly
fine ... he wasn't using a perl-function in a wrong way.
Cheers,
Tink
|
|
|
|
02-05-2008, 07:03 PM
|
#6
|
|
Member
Registered: May 2007
Distribution: Debian
Posts: 754
Rep:
|
Quote:
Originally Posted by Tinkster
You are wrong ...
rename is a perl-script included in debian based distros,
and the invocation "David the H" was using is perfectly
fine ... he wasn't using a perl-function in a wrong way.
|
Thanks for the info: I didn't know about "rename" as a command by itself. I took it for a very ugly piece of "real" perl. Thanks.
|
|
|
|
02-05-2008, 07:32 PM
|
#7
|
|
Senior Member
Registered: Aug 2006
Posts: 2,695
|
Quote:
Originally Posted by TheFutonEng
Hello, I am trying to write a very basic shell script to replace white space in file and directory names with underscores. I realize that there are probably several better ways to do this. Here is what I have come up with so far with two small scripts:
wsfind
Code:
#!/bin/bash
directory=$1
find $directory -name '* *' -exec wsrem \"{}\" \;
wsrem
Code:
#!/bin/bash
input=$1
echo $input
files=$(echo $input | tr ' ' _ | tr \" ' ') #replace white space with _ and remove quotes.
echo $files
mv -v $input $files
I have created some test files/directories and here is the output I get:
Code:
root@underwearless:~# wsrem test/
"test/this is a test"
test/this_is_a_test
mv: target `test/this_is_a_test' is not a directory
"test/this is a test/this is a test"
test/this_is_a_test/this_is_a_test
mv: target `test/this_is_a_test/this_is_a_test' is not a directory
"test/fjkd ls"
test/fjkd_ls
mv: target `test/fjkd_ls' is not a directory
Bash seems to be creating the string I want but they aren't be interpreted by mv correctly. Any thought on how to fix what I have or perhaps a better idea on how to implement this?
|
1) make sure you have created the "test" directory
2) are you running your script in "test" directory or somewhere else.
3) you can make use of the -p switch of mv command.
4) as tinkster has mentioned, use double quotes
|
|
|
|
02-08-2008, 05:55 PM
|
#8
|
|
LQ Newbie
Registered: Dec 2007
Posts: 2
Original Poster
Rep:
|
Using 'rename' worked out very well. Thanks for all of your help.
|
|
|
|
03-27-2011, 01:06 PM
|
#9
|
|
LQ Newbie
Registered: Apr 2010
Posts: 4
Rep:
|
Quote:
Originally Posted by David the H.
rename 's/ /_/g' file name
|
This worked perfectly for me.
Thx to the original poster.
|
|
|
|
04-30-2011, 11:01 AM
|
#10
|
|
LQ Newbie
Registered: Feb 2011
Posts: 2
Rep:
|
Whitespace cleanup and more
The detox command is pretty useful, although not nearly as much fun as writing awk, sed and Perl scripts.
|
|
|
|
02-21-2012, 08:05 PM
|
#11
|
|
LQ Newbie
Registered: Feb 2012
Posts: 2
Rep: 
|
Quote:
Originally Posted by FrDarryl
The detox command is pretty useful, although not nearly as much fun as writing awk, sed and Perl scripts.
|
Thanks for pointing me to the detox command. It sure saved a lot of work!
Best, Ed
|
|
|
|
02-22-2012, 06:10 AM
|
#12
|
|
LQ Newbie
Registered: Feb 2011
Posts: 2
Rep:
|
Quote:
Originally Posted by edrubins
Thanks for pointing me to the detox command. It sure saved a lot of work!
Best, Ed
|
Happy to help.
If you get in a bind with a filename you can't address with detox or any other command (like a failed inline bash command), you can mv or rm the file using its (file-system-unique) inode.
Here's an example.
669:02/22@11.54 ~/tmp/ ls -1
file1
file2
670:02/22@11.54 ~/tmp/ touch "file3 is a failed >>! UNIX redirection"
671:02/22@11.54 ~/tmp/ ls -1
file1
file2
file3 is a failed >>! UNIX redirection
672:02/22@11.54 ~/tmp/ ls -i -1
17 file1
43 file2
137 file3 is a failed >>! UNIX redirection
673:02/22@11.55 ~/tmp/ find . -inum 137 -exec mv {} file3 \;
674:02/22@11.55 ~/tmp/ ls -i -1
17 file1
43 file2
137 file3
675:02/22@11.56 ~/tmp/ find . -inum 137 -exec rm {} \;
676:02/22@11.56 ~/tmp/ ls -i -1
17 file1
43 file2
677:02/22@11.57 ~/tmp/
Last edited by FrDarryl; 02-22-2012 at 06:14 AM.
|
|
|
|
02-25-2012, 06:44 PM
|
#13
|
|
LQ Newbie
Registered: Feb 2012
Posts: 2
Rep: 
|
Inodes - it's been a long time.
Quote:
Originally Posted by FrDarryl
Happy to help.
If you get in a bind with a filename you can't address with detox or any other command (like a failed inline bash command), you can mv or rm the file using its (file-system-unique) inode.
Here's an example.
669:02/22@11.54 ~/tmp/ ls -1
file1
file2
670:02/22@11.54 ~/tmp/ touch "file3 is a failed >>! UNIX redirection"
671:02/22@11.54 ~/tmp/ ls -1
file1
file2
file3 is a failed >>! UNIX redirection
672:02/22@11.54 ~/tmp/ ls -i -1
17 file1
43 file2
137 file3 is a failed >>! UNIX redirection
673:02/22@11.55 ~/tmp/ find . -inum 137 -exec mv {} file3 \;
674:02/22@11.55 ~/tmp/ ls -i -1
17 file1
43 file2
137 file3
675:02/22@11.56 ~/tmp/ find . -inum 137 -exec rm {} \;
676:02/22@11.56 ~/tmp/ ls -i -1
17 file1
43 file2
677:02/22@11.57 ~/tmp/
|
I hadn't thought about using iodes - in fact I haven't haven't thought about inodes in years. 
|
|
|
|
02-26-2012, 03:47 AM
|
#14
|
|
Guru
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,706
|
Here's my script:
Code:
for i in *
do
mv "$i" $(echo "$i" | tr [:upper:] [:lower:] | tr [:blank:] _ | sed 's|[^-._a-z0-9]||g')
done
This also makes everything lower case, but it can be modified not to do that:
Code:
for i in *
do
mv "$i" $(echo "$i" | tr [:blank:] _ | sed 's|[^-._a-zA-Z0-9]||g')
done
|
|
|
|
02-26-2012, 12:35 PM
|
#15
|
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,697
|
I'd recommend using a series of parameter substitutions, rather than a single ugly chain of tr/ sed commands. You can simply add, modify, or remove substitutions as necessary to get the name pattern you want.
Code:
shopt -s extglob #needed for the extended glob below
for i in *; do
new=${i,,} #lowercasing requires bash v.4+
new=${new//+([[:blank:]])/_} #see note below
new=${new//[^-._a-z0-9]}
mv "$i" "$new"
done
Note: The +() exended globbing pattern can be used to compress all sequential blank space into a single underscore. Remove it to have each character substituted individually. You might also consider using [:space:] instead, to catch potential newline characters as well.
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 04:04 PM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|