LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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

Reply
 
Search this Thread
Old 01-15-2010, 10:25 PM   #1
trist007
Member
 
Registered: May 2008
Distribution: Slackware
Posts: 972

Rep: Reputation: 56
I question on a bash script and filename spaces...


I have over 50 files names with spaces in them. I'm trying to use a for loop as such:

for filename in *.php

However, when I print the $filename in the script, the script prints out parts of the filename because of the spaces in the file name.

For example, say the file name was Star Quest.php

When the script executes one $filename would be Star and another Quest.php.

How could I account for this? Something like $'filename' I dunno.
 
Old 01-15-2010, 10:41 PM   #2
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Try using the `find` command?

Code:
for f in "$(find /folder/of/the/files -type f -name "*.php")"; do
 echo "$f"
done
Depending on what exactly you're doing with each filename, this would maybe want some modification or supporting code.

Sasha
 
Old 01-15-2010, 10:50 PM   #3
trist007
Member
 
Registered: May 2008
Distribution: Slackware
Posts: 972

Original Poster
Rep: Reputation: 56
I have over 50 html files that I have renamed to php files. I want to insert this code into all the php files.

Code:
<br><br>
<center>
<form action="test.php" method=post>
<textarea name="comments" cols=40 rows=6></textarea>
<p>
<input type="submit" value="post comment">
</form>
</center>
<br><br>
<?php
$file = fopen("test","r");

while(! feof($file))
  {
  echo fgets($file). "<br />";
  }

fclose($file);
?>
</body>
</html>
So I'm thinking of using this script(the one you just posted, thank you)

Code:
for f in "$(find . -type f -name "*.php")";do
  sed -e '/<\/body>/,$d' < $f > temp2.txt
  cat string >> temp2.txt
  grep '</body>' $f | head -1 >> temp2.txt
  sed -e '1,/</body>/d' < $f >> temp2.txt
  mv temp2.txt $f
done
But I still get each $f to be printed as a separate word. For example, the filename Star Quest.php will be printed as $f = Star and the next $f = Quest.php
 
Old 01-15-2010, 11:09 PM   #4
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
It would possibly help if you "quote" the "$f" variable (the filename), no?

Sasha

PS - Since you seem to have posted this problem, or a very closely related one, over there: http://www.linuxquestions.org/questi...sed...-782516/ I am going to have that thread merged with this one.

Thanks
 
Old 01-15-2010, 11:17 PM   #5
trist007
Member
 
Registered: May 2008
Distribution: Slackware
Posts: 972

Original Poster
Rep: Reputation: 56
I tried the "$f" solution but I get '$f' not a valid identifier error.
 
Old 01-16-2010, 09:47 AM   #6
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
You'd have to show us the entire process you run in the console. to figure out WHERE the problem with $f is occurring. But I do notice one thing up there in Post#3, and that is you are using a slash "/" as the sed special character (the field separator, so to speak) but the LHS (the regex) also contains a slash "/" which is probably causing sed to screw up. You want to use a different field separator for sed, and/or escape the slashes in the LHS.

Anyhow, please show us what you see exactly in the console, when you run the commands.

Sasha
 
Old 01-16-2010, 10:06 AM   #7
devnull10
Member
 
Registered: Jan 2010
Location: Lancashire
Distribution: Slackware Stable
Posts: 547

Rep: Reputation: 115Reputation: 115
You need to use the file command and use quotes:

Code:
find . -name "*.php" | while read i
do
  echo "$1"
done
 
Old 01-16-2010, 10:15 AM   #8
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
@ devnull10,

what file command? Do you mean "find" command? And, shouldn't that be a "$i" rather than a "$1", or is it just my font....
 
Old 01-16-2010, 11:08 AM   #9
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,458

Rep: Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941
Code:
for f in "$(find . -type f -name "*.php")" ; do
I think the problem here is that the quotes in red make the output of find to be interpreted as a single string (newlines included). I don't really know why, but I found that a reliable solution in bash is process substitution, as in:
Code:
while read f
do
  ls -l "$f"
done < <(find . -type f -name "*.php")
this does not spawn a sub-process (as a pipe would do) and let you manage spaces properly. Again, I don't know why, but it works!
 
Old 01-16-2010, 11:15 AM   #10
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
@ colucix -- cool, remains to be seen if this will work for the OP -- good call about the quotes; maybe we're not supposed to know why it works, if it does

One thing I'm leery of, is the "< <(..." construct. That doesn't always work, but on that, I do not know why.
 
Old 01-16-2010, 11:24 AM   #11
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,458

Rep: Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941
Quote:
Originally Posted by GrapefruiTgirl View Post
maybe we're not supposed to know why it works, if it does
He he... you're right!
 
Old 01-16-2010, 11:21 PM   #12
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,245
Blog Entries: 15

Rep: Reputation: 233Reputation: 233Reputation: 233
try to run:
Code:
echo <(:)
 
Old 01-17-2010, 12:48 AM   #13
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,458

Rep: Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941Reputation: 1941
@ konsolebox: great! Your example made me think of the reason why process substitution works in the code above. Indeed process substitution uses file descriptors to send its output to another process, so that the command
Code:
$ echo <(:)
/dev/fd/63
equals to passing a filename to echo: it just displays the filename as any other string passed as argument.

In the while loop discussed above, the process substitution feeds a file descriptor and its content is then passed to the loop through the input redirection. We can do the same with a real file and the result is the same (the loop over filenames with blank spaces works as expected) for example
Code:
$ cat testfile
Another Quest.php
Star Quest.php
$ while read f
> do
>   ls -l "$f"
> done < testfile
-rw-r--r-- 1 alex users 0 2010-01-16 18:00 Another Quest.php
-rw-r--r-- 1 alex users 0 2010-01-16 18:00 Star Quest.php
process substitution just let us avoid the creation of a temporary file containing the result of the the find command. The read built-in does the rest, since it reads the input one line at a time and assigns the content of the entire line to the shell variable "f", blank spaces included.

Instead the for loop doesn't work since it takes the values from a list of arguments and every blank space in the list is interpreted as a field separator. In theory the for loop would work if we could do this:
Code:
for f in "Another Quest.php" "Star Quest.php"
> do
>   ls -l "$f"
> done
-rw-r--r-- 1 alex users 0 2010-01-16 18:00 Another Quest.php
-rw-r--r-- 1 alex users 0 2010-01-16 18:00 Star Quest.php
but obviously a string containing double quotes at the right places is difficult to obtain from a command (not to mention it would be a waste of time, since we have the other methods cited above).

In summary it is the read statement that does the trick, not the process substitution. I can book a room in clinic, now!
 
Old 01-17-2010, 06:13 AM   #14
devnull10
Member
 
Registered: Jan 2010
Location: Lancashire
Distribution: Slackware Stable
Posts: 547

Rep: Reputation: 115Reputation: 115
Quote:
Originally Posted by GrapefruiTgirl View Post
@ devnull10,

what file command? Do you mean "find" command? And, shouldn't that be a "$i" rather than a "$1", or is it just my font....
Yes, you are right on both - that's what typing just after a sleep does to you, lol!


so, you use the find
Code:
find . -name "*.php" | while read i
do
  echo "$i"
done
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
bash script - get filename created by script using variables aolong Linux - General 8 11-19-2009 12:40 PM
Bash script to remove capitalisation and spaces form a filename scuzzman Programming 11 05-18-2008 12:28 PM
Script: lame stumbles on spaces in filename browny_amiga Linux - General 5 05-14-2008 08:14 AM
bash, cp and filename (with spaces) woes dfidler Programming 9 04-10-2007 11:12 PM
bash script with spaces Quantum0726 Programming 2 11-14-2005 09:26 PM


All times are GMT -5. The time now is 01:30 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration