Optimize bash script?

There should be a way to stream these three search strings in my crudely constructed script below ...

#!/usr/bin/bash # # if [ "find /data -type f -perm 400 -print" ] ; then find /data -type f -perm 400 -exec echo Modifying {} \; find /data -type f -perm 400 -print | xargs chmod 755 else echo 'No files to modify' fi 
+4
source share
2 answers

You can change it to the following:

 found=$(find /data -type f -perm 400 -print -quit) if [ "$found" ]; then find /data -type f -perm 400 -exec echo Modifying {} \; -exec chmod 755 {} \; else echo 'No files to modify` fi 

Explanation:

  • find /data -type f -perm 400 -print -quit : as soon as it finds the very first file with a resolution of 400 in /data , it prints the file name and immediately stops the search. The print is saved in the found variable (So, we know whether to print "No files to change" or not later).
  • -exec echo Modifying {} \; -exec chmod 755 {} \; : You can execute several commands for each result returned by searching through this chain syntax.
  • Note: apparently find returns 0 when nothing is found, so using $? does not work here.
+4
source
 while read -d $'\0' file; do found=yes echo "Modifying $file" chmod 755 "$file" done < <(find /data -type f -perm 400 -print0) if [ "x$found" != "xyes" ]; then echo "No files found to modify" fi 

This uses the process replace function in Bash . It is equivalent

 find ... | while read ... 

except that while read is executed in a subshell, so we cannot set the variables that will be visible in the outer shell. Instead, we can use process substitution. <(cmd) starts cmd in a subshell, and its standard output is redirected to the named pipe. The name of this pipe is replaced with an external command.

Then we use < to redirect from this channel to the standard input of the while read command, which in turn reads each delimited record and stores the value in the specified name ( file in this case). By default, read split into newlines. For most files this will be fine; You can do:

 while read file; do ... done < <(find /data -type f -perm 400) 

and all will be well. But it is technically possible to have a new line in the file name, in which case it will break. The -print0 argument to search and the -d $'\0' read argument forces them to use an empty character as a delimiter, which is not valid in the file name.

+4
source

Source: https://habr.com/ru/post/1446315/


All Articles