0

I'm learning how to make script "fool-proof". I have some scripts that modify files in the current folder but they also modify the script itself. I know it all boils down to the "for" loop with "find" I can't get right.

for f in $(find . -type f | grep -v $0)

My goal is to include all files it can find from the current catalogue and it's sub-catalogues but exclude the executed script itself. It's working with grep -v but now it's excluding every file that includes the name of the script (like copies of the script in the subfolders). Anyone knows how to make it work only for the executed script? I must assume someone might change the name at some point, so excluding it by hand is out of the question.

  • Lose the grep. Use find . -type f ! -path $0 ? – steve Nov 20 '18 at 18:41
  • Tried that already since most answers suggest that. It's not working at all. It's including everything. – DrAhzek Nov 20 '18 at 18:45
  • Why not simply move the script to another place, like one directory up or to a dedicated directory for executables, such as $HOME/local/bin or similar? – Kusalananda Nov 20 '18 at 18:48
  • This is a non-problem. The rm executable does not prevent a user with the right privileges from deleting it. It's just that it more often applied to other files. Likewise, just move your script. – Kusalananda Nov 20 '18 at 18:56
  • It is impossible to make anything foolproof because fools are so ingenious. – doneal24 Nov 20 '18 at 19:00
1

Example of the find . -type f ! -path $0 approach. Note how the script only reports the foo.sh within the "d" directory. Not the foo.sh in the current directory.

$ find . -print
.
./a
./b
./c
./foo.sh
./d
./d/foo.sh
$ cat foo.sh
#!/bin/bash
for f in $(find . -type f ! -path $0); do
echo $f
done
$ ./foo.sh
./a
./b
./c
./d/foo.sh
$

Alternatively, try for f in $(find . -type f | grep -v "^\./foo\.sh$"); do

  • grep -vxF "$0" for that last bit, but why grep pathnames at all as they may contain embedded newlines. – Kusalananda Nov 20 '18 at 18:58
  • 1
    @steve Thank you! Your alternative is working like I've wanted to make it work! It really helped me with understanding how to adress files in grep. Gonna experiment on other variations now :) – DrAhzek Nov 20 '18 at 19:21
0

What is wrong with:

for f in $(find . -type f); do
 case $f in 
  */$0|$0)
     continue
  ;;
  *)
     echo 'Do something'
  ;;
 esac
 fi
done 
  • What if there is another file down in the directories with the same name as the script that one does want the script to process? Also: Why is looping over find's output bad practice? – Kusalananda Nov 20 '18 at 18:53
  • I know, but the user wants to loop it. If the file has exactly the same name, it will be not processed. But if it have a similar name but not exactly the same name it will be ignored.... but with only a simple adjust this behavior can be corrected... – Luciano Andress Martini Nov 20 '18 at 18:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.