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.

6
  • Lose the grep. Use find . -type f ! -path $0 ?
    – steve
    Commented Nov 20, 2018 at 18:41
  • Tried that already since most answers suggest that. It's not working at all. It's including everything.
    – DrAhzek
    Commented Nov 20, 2018 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
    Commented Nov 20, 2018 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
    Commented Nov 20, 2018 at 18:56
  • It is impossible to make anything foolproof because fools are so ingenious.
    – doneal24
    Commented Nov 20, 2018 at 19:00

2 Answers 2

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

2
  • grep -vxF "$0" for that last bit, but why grep pathnames at all as they may contain embedded newlines.
    – Kusalananda
    Commented Nov 20, 2018 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
    Commented Nov 20, 2018 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 
2
  • 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
    Commented Nov 20, 2018 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... Commented Nov 20, 2018 at 18:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .