-2

I'm using find to list all the files with a given UID and GID. I'm storing the file list in a temp file because I need to print out different attributes of this file set. One of these attributes is the files that have the install GID. I put the contents of the temp file into an array:

a=$( < $tmpfile)

The contents of tmpfile are like this for the cups package:

/usr/share/cups
/usr/share/cups/banners
/usr/share/cups/data
/usr/share/cups/doc-2.2.6
/usr/share/cups/doc-2.2.6/apple-touch-icon.png
/usr/share/cups/doc-2.2.6/cups.css
/usr/share/cups/doc-2.2.6/cups-printable.css
/usr/share/cups/doc-2.2.6/de
/usr/share/cups/doc-2.2.6/de/index.html
/usr/share/cups/doc-2.2.6/es
/usr/share/cups/doc-2.2.6/es/index.html
/usr/share/cups/doc-2.2.6/help
/usr/share/cups/doc-2.2.6/help/accounting.html
/usr/share/cups/doc-2.2.6/help/api-admin.html
/usr/share/cups/doc-2.2.6/help/api-filter.html
/usr/share/cups/doc-2.2.6/help/api-ppd.html
/usr/share/cups/doc-2.2.6/help/api-raster.html
/usr/share/cups/doc-2.2.6/help/cgi.html
/usr/share/cups/doc-2.2.6/help/cupspm.html
/usr/share/cups/doc-2.2.6/help/encryption.html

and so on ....

and then search the array like so:

echo "files with group install"
for file in ${a[@]}; do
  find $file -type f -user $userid -group install -exec ls -l {} \;
  find $file -type d -user $userid -group install -exec ls -ld {} \;
done

The second find here prints out the files under the directory and so any sub-directories with the install GID are printed twice. This is despite the presence of ls -ld. So the result for cups looks like:

drwxrwxr-t 16 cups install 4096 Dec  1 17:28 /usr/share/cups
drwxrwxr-t 2 cups install 4096 Dec  1 17:28 /usr/share/cups/ppdc
drwxrwxr-t 2 cups install 4096 Dec  1 17:21 /usr/share/cups/model
drwxrwxr-t 2 cups install 4096 Dec  1 17:28 /usr/share/cups/banners
drwxrwxr-t 3 cups install 4096 Dec 13 16:53 /usr/share/cups/drv
drwxrwxr-t 2 cups install 4096 Dec 13 16:53 /usr/share/cups/mime
drwxrwxr-t 2 cups install 4096 Dec  1 17:28 /usr/share/cups/data
drwxrwxr-t 2 cups install 4096 Dec  1 17:26 /usr/share/cups/usb
drwxrwxr-t 2 cups install 4096 Dec  1 17:28 /usr/share/cups/banners
drwxrwxr-t 2 cups install 4096 Dec  1 17:28 /usr/share/cups/data
drwxrwxr-t 3 cups install 4096 Dec 13 16:53 /usr/share/cups/drv
drwxrwxr-t 2 cups install 4096 Dec 13 16:53 /usr/share/cups/mime
drwxrwxr-t 2 cups install 4096 Dec  1 17:21 /usr/share/cups/model
drwxrwxr-t 2 cups install 4096 Dec  1 17:28 /usr/share/cups/ppdc
drwxrwxr-t 2 cups install 4096 Dec  1 17:26 /usr/share/cups/usb

I know find is recursive but surely it should honor the exec command and just print the long form of the directory.

for (( i=0; i<${#a[@]}; i++ )); do
#    for file in ${a[@]}; do
 find ${a[i]} -user $userid -group install -type f -exec ls -l {} \;
 find ${a[i]} -user $userid -group install -type d -exec ls -ld {} \;
done

gives the same result.

  • s/enter echo/echo/ – user1375531 Jan 9 '18 at 20:36
  • Do not comment on your own question; edit it instead. – Hauke Laging Jan 9 '18 at 20:36
  • 1
    Please: Edit your question and provide an example of the first find, or some entries in tmpfile. – Isaac Jan 9 '18 at 20:39
  • You should use for file in "${a[@]}" and find "$file" – Hauke Laging Jan 9 '18 at 20:44
  • Using double quotes concatenates all the filenames with \n between each filename. – user1375531 Jan 9 '18 at 20:59
0
find $file -type d -user $userid -group install -exec ls -ld {} \;

This will recurse into $file, and run ls -ld on all directories within it. So if the list you loop over also contains the subdirectories, you'll get them again. First when find recurses starting at the main directory, then for every time the subdirectories are listed.

Compare:

$ mkdir -p dir1/subdir
$ for f in dir1 dir1/subdir ; do find "$f" -type d -exec ls -1d {} \; ; done
dir1
dir1/subdir
dir1/subdir

I'm not exactly sure what you want to do here, for listing just the file currently being processed (in $file), you don't need find at all, just ls -ld $file should do. Though if you're using find to only print files owned by a given user, you might use -maxdepth 0 to prevent find from recursing. At all.

$ for f in dir1 dir1/subdir ; do find "$f" -maxdepth 0 -type d -exec ls -1d {} \; ; done
dir1
dir1/subdir

But then I wonder if it would be better to just find the directory/-ies under which all the files are (/usr/share/cups, here) and just run find -user ... -group ... -exec ls -ld {} + on that.


As for a, the assignment a=$( < $tmpfile) just assigns a string to a. Which in the shell is the same as a[0], and ${#a[@]} also just returns 1 since a scalar is in sense a single-element array. To make it an actual array, you'd need to assign a=( $(< $tmpfile) ), but that just makes the splitting on whitespace happen earlier.

You might want to use while read ... to read the input file instead. See BashFAQ 001.

  • I'm trying to pull out all the cups files that are set with GID=install and a whole bunch of different attributes that I haven't shown. Adding -maxdepth 0 fixed the problem. Thanks. – user1375531 Jan 9 '18 at 21:39

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.