LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   Find command issues over while loop or for loops (https://www.linuxquestions.org/questions/linux-general-1/find-command-issues-over-while-loop-or-for-loops-4175460803/)

balakrishnay 05-05-2013 12:02 PM

Find command issues over while loop or for loops
 
Hi All,

The below find command returns nothing sometimes , if so it wont even enter into the loop to continue with rest of the code how to handle this ?

Appreciated your help ASAP.


for file in `find /oracle/admin/XXXXX/udump/bkp/ -type f -size +20M -exec ls -1 {} \;`

do
if [ ! -f "$file" ]
then
echo "File \"$file\" does not exist."
exit 1
fi
proc=`echo $file | awk -F"_" '{print $3}'`
active_pid=`ps aux | grep "$proc" | grep -v grep|wc -l`

if [ "$active_id" -eq 1 ]
then
exec "/usr/tools/oracle/Standard/script/DB_Trace_Off.ksh" $INST_NAME $active_pid
else
gzip $file
fi

done

Regards
Bala

unSpawn 05-05-2013 02:51 PM

Code:

#!/bin/bash -vx
for file in `find /oracle/admin/XXXXX/udump/bkp/ -type f -size +20M -exec ls -1 {} \;`

  do
  if [ ! -f "$file" ]
  then
      echo "File \"$file\" does not exist."
        exit 1
  fi
      proc=`echo $file | awk -F"_" '{print $3}'`
      active_pid=`ps aux | grep "$proc" | grep -v grep|wc -l`

  if [ "$active_id" -eq 1 ]
  then
        exec "/usr/tools/oracle/Standard/script/DB_Trace_Off.ksh" $INST_NAME $active_pid
  else
        gzip $file
  fi

done
exit 0

Run that as '/path/to/script 2>&1 | tee /tmp/output.txt' and then read back the "output.txt" file, see what 'find' finds and how it's used in the script.

*And since you mentioned the ASAP FLA you will also want to read these:
http://mywiki.wooledge.org/ParsingLs
http://mywiki.wooledge.orgDontReadLinesWithFor
http://mywiki.wooledge.org/UsingFind
http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes
as there's nothing quicker than you reading stuff yourself.

suicidaleggroll 05-05-2013 08:48 PM

Quote:

Originally Posted by balakrishnay (Post 4945447)
Hi All,

The below find command returns nothing sometimes , if so it wont even enter into the loop to continue with rest of the code how to handle this ?

Of course it doesn't enter the for loop. The for loop is looping over each match from find, if find doesn't find anything, there's nothing for the for loop to do. What, exactly, would you like for the code to do in this case, since it sounds like it's doing exactly what it's supposed to be doing.

Beryllos 05-06-2013 03:13 AM

If there is something you need to do when the find command doesn't find anything, you could test for that and take the appropriate action, for example:
Code:

#!/bin/bash
FILE_LIST=$(find . -type f -print) # by the way, I use -print instead of -exec ls -1 {} \;
if [ -z "$FILE_LIST" ] # test for zero-length string (no files found)
then
    echo "The file list is empty."
else
    for FILE in $FILE_LIST
    do
        echo "list item:" $FILE
    done
fi

When there are no files to be found, I get:
Code:

tony> ../looptest
The file list is empty.

When there are files called Alice, Bob, and Charlie, I get:
Code:

tony> ../looptest
list item: ./Charlie
list item: ./Alice
list item: ./Bob

Slightly off-topic: Neither my script nor the script in the OP works correctly if the filename has whitespace (like "Bob Marley"). Then the output for 3 files appears to have more than 3 items:
Code:

tony> ../looptest
list item: ./Bob
list item: Marley
list item: ./Charlie
list item: ./Alice

This is because of the way the "for loop" processes lists which are delimited by whitespace. I have read the man pages of find, for, and ls, and I have tried a few tricks, but so far I have not found a solution to this particular problem. Similar problems may exist also when other special characters are present in the filename.

suicidaleggroll 05-06-2013 09:07 AM

Quote:

Originally Posted by Beryllos (Post 4945785)
[/CODE]Slightly off-topic: Neither my script nor the script in the OP works correctly if the filename has whitespace (like "Bob Marley"). Then the output for 3 files appears to have more than 3 items:
Code:

tony> ../looptest
list item: ./Bob
list item: Marley
list item: ./Charlie
list item: ./Alice

This is because of the way the "for loop" processes lists which are delimited by whitespace. I have read the man pages of find, for, and ls, and I have tried a few tricks, but so far I have not found a solution to this particular problem. Similar problems may exist also when other special characters are present in the filename.

The easiest solution is to use "while read" instead of "for":
Code:

find . | while read -r file

Beryllos 05-06-2013 03:33 PM

One More Thing...
 
Quote:

Originally Posted by suicidaleggroll (Post 4945939)
The easiest solution is to use "while read" instead of "for":
Code:

find . | while read -r file

Thanks. That works great for filenames with whitespace. Just to make it more interesting, I created files called "*" and "--help"
Code:

tony> ls
*  Alice  Bob Marley  Charlie  --help

which lead to all sorts of confusion with everyday bash commands. However, if I use double quotes as shown in the first line below, it seems to work:
Code:

tony> find . -type f | while read -r file; do echo "$file"; cat "$file"; rm -v "$file"; done
./Bob Marley
This is the contents of file named "Bob Marley"
removed ‘./Bob Marley’
./*
This is the contents of file named "*"
removed ‘./*’
./--help
This is the contents of file named "--help"
removed ‘./--help’
./Charlie
This is the contents of file named "Charlie"
removed ‘./Charlie’
./Alice
This is the contents of file named "Alice"
removed ‘./Alice’
tony> ls


sundialsvcs 05-06-2013 06:11 PM

As a general rule-of-thumb, in any language or environment, "finders" need to be allowed to "do their own thing, whatever it is, without interruption." If you need to process the list-of-whatevers that they create, then you should plan to "let them generate it, completely, however they want to do it," first, then "iterate through the list that they produced."

rknichols 05-06-2013 06:11 PM

Try it on a filename that contains a newline character.

Beryllos 05-06-2013 08:19 PM

Quote:

Originally Posted by rknichols (Post 4946195)
Try it on a filename that contains a newline character.

Okay, I tried it. The method I outlined above does not work.
Code:

tony> FILE=`echo -e new'\n'line`
tony> echo Hello World\! > "$FILE"
tony> ls
new?line
tony> ls --show-control-chars
new
line
tony> find . -type f | while read -r file; do rm -v "$file"; done
rm: cannot remove ‘./new’: No such file or directory
rm: cannot remove ‘line’: No such file or directory
tony> rm -v new?line
removed ‘new\nline’

I guess that makes sense because the read command expects items to be separated by newline characters.


All times are GMT -5. The time now is 12:32 AM.