#!/bin/csh -f # xattr_detect # ------------------------------------------------------------------------- # C shell script to detect whether the specified Mac OS X attribute # exists on the specified file. Return 0 if exists. # ------------------------------------------------------------------------- # Revision History: # $Log$ # ------------------------------------------------------------------------- if ($#argv != 2 || $1:q == "-h" || $1:q == "--help") then echo "Usage: $0:t attribute filename..." exit 1 endif # Note: This didn't work for some reason. Callers didn't get the expected # status value. Had to put the same xattr line in the caller instead. # Was also MUCH slower using xattr than using "ls". # xattr -p $1:q $2:q >& /dev/null # exit $status # Capture output of ls including attribute names and values # Note: We use 3 types of quotes here. Double quotes (") to enclose # the right hand side, backticks (`) to execute the ls command, # and single quotes (') to around $2:q. Don't mess with them! # We need explicit quotes around $2:q despite the use of :q as # one of: # ls -l@ "$2:q" # ls -l@ '$2:q' # They probably name the :q unnecessary, but we'll ignore that. # Without them, as: # ls -l@ $2:q # ls splits the filename at spaces and can't find files with each # partial name. It reports errors like: # ls: 16.46.00.jpg: No such file or directory # ls: 2021-04-12: No such file or directory # Also, we have to enclose the entire right side in quotes, as: # "`ls -l@ '$2:q'`" # Otherwise, the tab chars used by ls to delimit the attribute # name are not preserved. Assigning an unquoted string to a # shell variable as: # set ls_output = `ls -l@ "$2:q"` # tokenizes the parts of the unquoted string, converting each # sequence of whitespace to a single space, to form the string # value assigned to the variable ls_output. # So we'd get a false positive on filenames that contained the # space-separated attribute name. And on files with attribute # data that contained the space-separated attribute name. It's # more reliable to enclose the right side in quotes to preserve # the tabs. # But if we use single quotes to enclose the entire right side, as: # '`ls -l@ "$2:q"`' # the backticks are no longer special, so the ls command doesn't # run at all. # Therefore, we have to use double quotes to enclose the right side. # To avoid nesting quotes of the same type, and dealing with # "escape hell" involving lots of backslashes, we use single # quotes for $2:q. set ls_output = "`ls -l@ '$2:q'`" # Check for attribute name as a substring # Note: The =~ operator compares left arg with right glob pattern # Note: The delimiters around $1 below must be literal tab chars, not # spaces, since that's what the ls output uses. And can't use # \t for tab here. Beware editors and pretty printers that # convert these tabs to spaces. if ("$ls_output" =~ "* $1 *") exit 0 exit 1