You are not logged in.

#1 2011-09-05 20:26:05

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

find in a for loop with spaces chokes [SOLVED]

I have a need to use find in a for loop so I can process a number of different filetypes.  Problem is these are all my old word files which are FULL of spaces (pre-Linux days).  Without the for loop, my find statement works in this very simple example:

$ find . -type f \( -iname "*.doc" -o -iname "*.docx" \)
./getit.docx
./get it.doc
./getit.doc

But.... with the for loop, the space messes up the find:

$ for i in `find . -type f \( -iname "*.doc" -o -iname "*.docx" \)`; do echo "$i"; done
./getit.docx
./get
it.doc
./getit.doc

What am I doing wrong?

Last edited by graysky (2011-09-05 22:20:24)

Offline

#2 2011-09-05 20:30:23

karol
Archivist
Registered: 2009-05-06
Posts: 25,440

Re: find in a for loop with spaces chokes [SOLVED]

You need to quote your arguments.

[karol@black foo]$ for i in "$(find . -type f \( -iname "*.doc" -o -iname "*.docx" \))"; do echo "$i"; done
./getit.doc
./getit.docx
./get it.doc

I prefer $() to backtics.

Last edited by karol (2011-09-05 20:31:32)

Offline

#3 2011-09-05 20:42:54

lolilolicon
Member
Registered: 2009-03-05
Posts: 1,722

Re: find in a for loop with spaces chokes [SOLVED]

Filenames can contain not only spaces, but newlines, too.  This page is very helpful on the topic: http://mywiki.wooledge.org/BashFAQ/020


This silver ladybug at line 28...

Offline

#4 2011-09-05 20:43:59

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: find in a for loop with spaces chokes [SOLVED]

Oh, boy...

http://mywiki.wooledge.org/BashPitfalls … .2A.mp3.29
and
http://mywiki.wooledge.org/BashFAQ/020

EDIT: lolilolicon beat me to it!

Last edited by sisco311 (2011-09-05 20:44:41)


don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#5 2011-09-05 20:50:26

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

Wow, immediate and accurate response.  Thanks guys!

A follow-up... why is my code to chop off the file extension here not working?  The expected output should be the original file then the original file minus the file extension:

cat ~/bin/fix
#!/bin/bash
for i in "$(find . -type f \( -iname "*.doc" -o -iname "*.docx" \))" ; do
  out="${i%.*}"
  echo "$i"
  echo "$out"
done

$ fix
./getit.docx
./get it.doc
./getit.doc
./getit.docx
./get it.doc
./getit

Last edited by graysky (2011-09-05 20:51:59)

Offline

#6 2011-09-05 20:53:04

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: find in a for loop with spaces chokes [SOLVED]

Immediate, accurate, and you ignored it. Use a while loop, properly terminated with nulls.

while read -r -d '' file; do
  # do stuff with "$file" and remember to quote it on expansion
done < <(find ... -print0)

Offline

#7 2011-09-05 20:57:45

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

@falconindy - your code worked great, but I don't understand it smile  Is my construct doomed to fail?  ..and how did I ignore the quoting on the links?

Offline

#8 2011-09-05 21:08:10

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: find in a for loop with spaces chokes [SOLVED]

Please read the links.

In your loop the entire output of the find command is threated as a single word.

j=0; for i in "foo
bar
file"; do     printf '%s\n' "$i"; ((j++)); done; printf '%d\n' $j

Last edited by sisco311 (2011-09-05 21:12:03)


don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#9 2011-09-05 21:15:50

Wintervenom
Member
Registered: 2008-08-20
Posts: 1,011

Re: find in a for loop with spaces chokes [SOLVED]

find -iregex '.*\.docx?$' -printf '%f\n'

...or...

find -iregex '.*\.docx?$' -exec thing_you_want_to_do {} \;

Last edited by Wintervenom (2011-09-05 21:17:56)

Offline

#10 2011-09-05 21:29:31

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

Thanks for the tips sisco and winterv.  I read the links, but I think they're written for someone with more experience/understanding.  I understand what's wrong with my syntax, but I don't know how to accomplish what I want to do knowing that all the output is treated as one word.

I need to find all files ending in the following formats: .doc .docx .ppt .pptx .xls .xlsx then strip off the extension storing it in a variable, and finally process both the original files as the input of another script and keep the file stem as the output of that same script:

/path/to/script -i originalfile.docx -o originalfile

Last edited by graysky (2011-09-05 21:32:40)

Offline

#11 2011-09-05 21:43:07

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: find in a for loop with spaces chokes [SOLVED]

while IFS= read -r -d'' file
do
    yourscript -i "$file" -o "${file%.*}"
done< <(find ./ -iname '*.doc' -print0)

modify the find command to fit your needs.

or

If you have to run the command in the file's directory:

find ./ -iname \*.doc -execdir bash -c 'yourscript  -i "$1" "${1%.*}"' _ {} \;

Last edited by sisco311 (2011-09-05 21:46:51)


don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#12 2011-09-05 21:59:55

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

@sisco - thanks for the code.  The most simple test of it would be to simply echo the results, but I get a null when I do it.

while IFS= read -r -d'' file
do
echo "$file" "${file%.*}"
done< <(find ./ -iname '*.doc' -print0)

Offline

#13 2011-09-05 22:02:39

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: find in a for loop with spaces chokes [SOLVED]

I missed a space after read's -d option. Sorry.

while IFS= read -r -d '' file....

don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#14 2011-09-05 22:13:38

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

@sisco - ok, this is working.  Thank you.  How can I add multiple extensions to the find like I did in my first post to catch all 6 of them?  The same format isn't accepted here.

Offline

#15 2011-09-05 22:16:31

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: find in a for loop with spaces chokes [SOLVED]

It should work. Th e-print0 action must be the last:

done< <(find ./ \( -iname '*.doc' -o -iname '*docx' \) -print0)

If you need a -type f test put it after the -name  (-regex) tests, you don't want to check each file only the .doc, .docx .... files:

done< <(find ./ \( -iname '*.doc' -o -iname '*docx' \) -type f -print0)

Last edited by sisco311 (2011-09-05 22:26:13)


don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#16 2011-09-05 22:17:30

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

@sisco3 - FINALLY.  Thanks everyone for their help with this frustrating problem.

find -regex '.*\.\(ppt\|pptx\|xls\|xlsx\|doc\|docx\)' -print0

Here is the complete code:

while IFS= read -r -d '' file
do
  echo "$file" "${file%.*}"
done< <(find -regex '.*\.\(ppt\|pptx\|xls\|xlsx\|doc\|docx\)' -print0)

Last edited by graysky (2011-09-05 22:20:14)

Offline

#17 2011-09-13 08:10:58

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

I've been searching for a while now but have come up empty-handed.  Can someone post a link to a guide showing additional usage of the syntax in the following line?

echo "$file" "${file%.*}"

Rather than echoing the /path/to/filename.extension <<<space>>> /path/to/filename as the code above does. What would the syntax look like to echo: /path/to?

Offline

#18 2011-09-13 08:17:20

lolilolicon
Member
Registered: 2009-03-05
Posts: 1,722

Re: find in a for loop with spaces chokes [SOLVED]

You want:

echo "${file%/*}"

See the Parameter Expansion section of bash(1).


This silver ladybug at line 28...

Offline

#19 2011-09-13 08:25:22

karol
Archivist
Registered: 2009-05-06
Posts: 25,440

Re: find in a for loop with spaces chokes [SOLVED]

Try 'dirname':

[karol@black ~]$ for file in $(find /home/karol/test/foo3 -type f); do echo $(dirname "$file") "$file"; done
/home/karol/test/foo3 /home/karol/test/foo3/three.baz
/home/karol/test/foo3 /home/karol/test/foo3/two.bar
/home/karol/test/foo3 /home/karol/test/foo3/one.foo

Offline

#20 2011-09-13 10:47:25

sisco311
Member
From: Romania
Registered: 2008-05-23
Posts: 112

Re: find in a for loop with spaces chokes [SOLVED]

Both dirname and the parameter expansion are POSIX. PE seams more 'elegant', so in this case I'd go with it. smile


don't drink unwashed fruit juice.
i never make predictions, especially about the future.

Offline

#21 2011-09-13 20:18:39

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: find in a for loop with spaces chokes [SOLVED]

@lolilolicon - nice!  exactly what I needed.  Parameter Expansion

Offline

Board footer

Powered by FluxBB