kartoza-geek
kartoza-geek

Reputation: 349

bash scripting and conditional statements

I am trying to run a simple bash script but I am struggling on how to incoperate a condition. any pointers. the loop says. I would like to incoperate a conditions such that when gdalinfo cannot open the image it copies that particular file to another location.

for file in `cat path.txt`; do gdalinfo $file;done

works fine in opening the images and also shows which ones cannot be opened.
the wrong code is

for file in `cat path.txt`; do gdalinfo $file && echo $file; else cp $file /data/temp

Upvotes: 2

Views: 306

Answers (2)

clt60
clt60

Reputation: 63892

Again, and again and again - zilion th again...

Don't use contsructions like

for file in `cat path.txt`

or

for file in `find .....`
for file in `any command what produces filenames`

Because the code will BREAK immediatelly, when the filename or path contains space. Never use it for any command what produces filenames. Bad practice. Very Bad. It is incorrect, mistaken, erroneous, inaccurate, inexact, imprecise, faulty, WRONG.

The correct form is:

for file in some/*   #if want/can use filenames directly from the filesystem

or

find . -print0 | while IFS= read -r -d '' file

or (if you sure than no filename contains a newline) can use

cat path.txt | while read -r file

but here the cat is useless, (really - command what only copies a file to STDOUT is useless). You should use instead

while read -r file
do
   #whatever
done < path.txt

It is faster (doesn't fork a new process, as do in case of every pipe).

The above whiles will fill the corect filename into the variable file in cases when the filename contains a space too. The for will not. Period. Uff. Omg.

And use "$variable_with_filename" instead of pure $variable_with_filename for the same reason. If the filename contains a white-space any command will misunderstand it as two filenames. This probably not, what you want too..

So, enclose any shell variable what contain a filename with double quotes. (not only filename, but anything what can contain a space). "$variable" is correct.

If i understand right, you want copy files to /data/temp when the gdalinfo returns error.

while read -r file
do
   gdalinfo "$file" || cp "$file" /data/temp
done < path.txt

Nice, short and safe (at least if your path.txt really contains one filename per line).

And maybe, you want use your script more times, therefore dont out the filename inside, but save the script in a form

while read -r file
do
   gdalinfo "$file" || cp "$file" /data/temp
done

and use it like:

mygdalinfo < path.txt

more universal...

and maybe, you want only show the filenames for what gdalinfo returns error

while read -r file
do
   gdalinfo "$file" || printf "$file\n"
done

and if you change the printf "$file\n" to printf "$file\0" you can use the script in a pipe safely, so:

while read -r file
do
   gdalinfo "$file" || printf "$file\0"
done

and use it for example as:

 mygdalinfo < path.txt | xargs -0 -J% mv % /tmp/somewhere

Howgh.

Upvotes: 6

devnull
devnull

Reputation: 123458

You can say:

for file in `cat path.txt`; do gdalinfo $file || cp $file /data/temp; done

This would copy the file to /data/temp if gdalinfo cannot open the image.

If you want to print the filename in addition to copying it in case of failure, say:

for file in `cat path.txt`; do gdalinfo $file || (echo $file && cp $file /data/temp); done

Upvotes: 1

Related Questions