3

How do you exit a script from within a find piped while loop?

E.g. following exit just exits the piped subshell:

find some_directory -type d|while read dir_name; do
  if [ -w "$dir_name" ]; then
    exit 1
  fi
done
4
  • 3
    You could not run it in a subshell done < <(find some_directory -type d), probs wanna use while IFS= read -r dir_name to handle dodge filenames just incase as well. Commented Apr 18, 2017 at 23:13
  • Why so complicated? find some_directory -type d ! -perm -u+w will give you all non-writable directories in directory Commented Apr 18, 2017 at 23:14
  • @the.Legend how do you get the return value of that find? $? is 0 whether or not a file was found Commented Apr 18, 2017 at 23:18
  • 1
    there are few ways: if you only want exit status then just make it like find some_directory -type d ! -perm -u+w | egrep '.*' The return status will be 0 when something is found, and non-zero otherwise. Alternatively you may play with wc -l or if you need to process files then just add -exec {} \; piece to find command Commented Apr 18, 2017 at 23:26

2 Answers 2

5

You can check the return status of the pipe:

if ! find some_directory -type d|while read dir_name; do
  if [ -w "$dir_name" ]; then
    exit 1
  fi
done; then exit 1; fi

Or, more simply:

 find some_directory -type d|while read dir_name; do
      [ -w "$dir_name" ] && exit 1
    done || exit 1
Sign up to request clarification or add additional context in comments.

Comments

4

In bash an exit invoked in a subprocess will exit the subprocess but not the parent process.

In OP's code the pipeline - find | while - will run the while (and the subsequent exit invocation) within a subprocess, so if/when the exit 1 is invoked the subprocess will be exited but not the parent process.

To allow the exit to apply at the top level we need to insure the while is not run within a subprocess. Expanding on 123's comment:

while read -r dir_name; do
  if [ -w "$dir_name" ]; then
    exit 1
  fi
done < <(find some_directory -type d)

Note that the <( ) construct ("process substitution") is not available in all shells, or even in bash when it's in sh-compatibility mode (i.e. when it's invoked as sh or /bin/sh). So be sure to use an explicit bash shebang (like #!/bin/bash or #!/usr/bin/env bash) in your script, and don't override it by running the script with the sh command.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.