LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   I question on a bash script and filename spaces... (https://www.linuxquestions.org/questions/programming-9/i-question-on-a-bash-script-and-filename-spaces-782520/)

trist007 01-15-2010 10:25 PM

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.

GrapefruiTgirl 01-15-2010 10:41 PM

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

trist007 01-15-2010 10:50 PM

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

GrapefruiTgirl 01-15-2010 11:09 PM

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

trist007 01-15-2010 11:17 PM

I tried the "$f" solution but I get '$f' not a valid identifier error.

GrapefruiTgirl 01-16-2010 09:47 AM

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

devnull10 01-16-2010 10:06 AM

You need to use the file command and use quotes:

Code:

find . -name "*.php" | while read i
do
  echo "$1"
done


GrapefruiTgirl 01-16-2010 10:15 AM

@ 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....

colucix 01-16-2010 11:08 AM

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! :)

GrapefruiTgirl 01-16-2010 11:15 AM

@ 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.

colucix 01-16-2010 11:24 AM

Quote:

Originally Posted by GrapefruiTgirl (Post 3828799)
maybe we're not supposed to know why it works, if it does ;)

He he... you're right! :)

konsolebox 01-16-2010 11:21 PM

try to run:
Code:

echo <(:)
:)

colucix 01-17-2010 12:48 AM

@ 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! ;)

devnull10 01-17-2010 06:13 AM

Quote:

Originally Posted by GrapefruiTgirl (Post 3828741)
@ 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



All times are GMT -5. The time now is 07:28 PM.