1

In trying to read all the values of the extended attributes on a single file, if I do

xattr -l <filename> | while read ATTR; do
  xattr -p $ATTR <filename>
done

I get what I expect.  But if I try to do multiple files with

for FILE in *; do
  echo "=== $FILE ==="
  xattr -l $FILE | while read ATTR; do
    xattr -p $ATTR $FILE
  done
done

for some files I get only the filename (no xattr, I suppose);
for some files I get

=== 154128428159.JPEG ===
xattr: [Errno 22] Invalid argument: '154128428159.JPEG'
xattr: 154128428159.JPEG: No such xattr: com.apple.macl: 
xattr: [Errno 22] Invalid argument: '154128428159.JPEG'
Not enough arguments for option -p. Expected at least 2 but got 1

and for other files,

xattr: [Errno 22] Invalid argument: 'record-image_-7.jpg'
xattr: record-image_-7.jpg: No such xattr: com.apple.macl: 
xattr: [Errno 63] File name too long: 'record-image_-7.jpg'

I tried putting unset ATTR or ATTR="" in the outer loop, but got the same results.

This is with either zsh or bash on macOS 13.5.2

3
  • Try it with just xattr $FILE, without any options. With the -l option, it will include the attribute values, which may include multiple lines and even empty lines.
    – Gairfowl
    Commented Sep 12, 2023 at 1:44
  • The values are what I want, as I said in the question. According to the man page, -l lists the names of the attributes. But it only allows one attribute at a time, hence looping on the names.
    – WGroleau
    Commented Sep 12, 2023 at 2:27
  • OK, the format of the man page confused me. -l changes the format rather than listing the values.
    – WGroleau
    Commented Sep 12, 2023 at 2:39

1 Answer 1

0

The man page format confused me and when Gairfowl explained that -l gives the values, I tested it with no options but (oops) the file I tested it on had no attributes.

So actually, I do need a loop, but it’s

for ATTR in $(xattr "$FILE"); do
  xattr -pl $ATTR "$FILE"
done
1
  • 1
    As always, use double quotes around $FILE to ensure it works with filenames containing whitespace. In case you still go with the outer loop (for file in *; do) you could also use if [ -f "$FILE" ]; then ... fi to only look at files (and skip directories etc).
    – nohillside
    Commented Sep 12, 2023 at 6:46

You must log in to answer this question.

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