7

I am looking to automate my xcode projects. It all works fine except the projects name with spaces. I have tried the following commands:

output_apps=`find ./ -name "*.app" -print`
output_apps=`find ./ -name "*.app"`

When I run

find ./ -name "*.app" -print 

without storing into variable, it gives me output as expected as mentioned below:

.//Ten EU.app
.//Ten Official App EU.app
.//Ten Official App.app
.//Ten.app

However when I store the output of above command in a variable as below

output_apps=`find ./ -name "*.app" -print`

and then run the following for loop for get the names

for curr_app in $o
do 
    echo "$curr_app"
done

It shows

.//Ten
EU.app
.//Ten
Official
App
EU.app
.//Ten
Official
App.app
.//Ten.app

How do I maintain the spaces between each output and get the following output?

Ten EU.app
Ten Official App EU.app
Ten Official App.app
Ten.app
2
  • 1
    There are couple of solutions here... One with while loop and read is really noteworthy. Commented Jan 9, 2013 at 23:09
  • the while loop worked when the names are extracted from the filename. However, I am extracting the required files after pipe redirection from xcodebuild command. Is there a way to put find as input in the while loop? Commented Jan 9, 2013 at 23:25

2 Answers 2

17

If you don't need to store the file names in a variable, you can use find -print0 in combination with xargs -0. This separates the found entries by NUL bytes instead of newlines. xargs reads these NUL separated values and calls some command with as many arguments as possible.

find ./ -name "*.app" -print0 | xargs -0 some-command

If you want, you can limit the number of arguments given to some-command with xargs -n 1

find ./ -name "*.app" -print0 | xargs -0 -n 1 some-command

Yet another approach is to read the files with a while loop

find ./ -name "*.app" -print | while read f; do
    some-command "$f"
done

This calls some command with one file at a time. The important point is to enclose the $f into double quotes.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @Olaf. The first two queries brings result .//Ten EU.app .//Tenn Official App EU.app .//Ten Official App.app .//Ten.app. I will try to put them in an array as suggested by ormaaj. If that fails, I will just create a temp file, put values and read it from there as suggested by zplesivcak. There is a lot more code and this small part has taken forever.
How to put them in array?
@vvn One way would be to use the while loop and add the values one by one. See also question stackoverflow.com/q/1951506/1741542
1

The file names may contain spaces. You need to ask find to separate them via NULL(\0). Use find -print0.

6 Comments

No force in the known universe can put a NUL byte into a bash variable.
I am sorry, I couldn't interpret your answer into complete command. I tried output=find ./ -name "*.app" -print0. How do I adjust NULL(\0)
@Vebz It isn't a complete answer. First you need the nonstandard (but common) -print0 feature (it's a good thing). Then you need a way to read NUL-delimited streams (Harder. Also generally not possible without non-standard extras. Have a look at Bash's read -d). If you need to store the results, you'll want to use an array.
A complete example would be for i in $(find -print0 | xargs -0 echo); do echo $i; done
@alinsoar your method brings the same result as mine. (Even when I add double quotes to "$i".
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.