1

I tried to code a bash script that loops through a given directory and all its subdirectories and extracts metadata attributes with the mdls command into separate text files. Since I have a lot of filenames containing spaces and other special characters, my code base is derived from the answer "Looping through files with spaces in the names?". But after each file the script waits for pressing Enter/Return manually.

How can I make it automatically loop through files and folders?

#!/bin/bash
# write metadata of files in separate file

find . -type f -name '*.*' -exec sh -c '
  for file do
    echo "$file"
    mdls "$file" > "$file"_metadata.txt
    read line </dev/tty
  done
' sh {} +
Madamadam
  • 117

2 Answers2

1
find /path/to/Users/myuser -type f -print0 | 
xargs -0 -I% sh -c "mdls "%" > "%"_metadata.txt"
Hellseher
  • 131
  • Thank you. Your script has an issue with spaces in filenames and doesn't grab files recursively in subdirectories. But your answer gave me a hint and I updated my code and my question: now the problem is narrowed down. – Madamadam Sep 23 '18 at 21:38
  • 1
    This also has problems with files with shell syntax characters (such as quotes or wildcard characters) in their names. And you may believe that that’s unlikely to happen, but remember: single quote and apostrophe are the same character.  It’s somewhat common for filenames to contain apostrophes. As a general rule, it’s dangerous to insert a filename directly into a shell command.  It’s better to provide the filename as an argument and then reference it with "$1" (or something similar). – G-Man Says 'Reinstate Monica' Sep 25 '18 at 17:04
  • OK, that handles many of the bad cases. It still has problems if a filename contains double quote characters ("); i.e., the ones you added to your answer. – G-Man Says 'Reinstate Monica' Sep 26 '18 at 15:44
1
  1. The read line </dev/tty command is reading a line from the terminal (i.e., the keyboard).  If you don’t want to do that, delete that command.
  2. Does the loop seem to be working well aside from that?  (At a glance, it looks pretty much OK to me.)  If not, edit your question to say what happens.
  3. -name '*.*' says to look only at files whose names contain a period (a.k.a. “dot”, .).  If you want to exclude files whose names don’t include a . (like data and README), then that’s the perfect way to do it.  But if you want to handle all files, leave off the -name clause — find looks at all files by default; clauses like -type f, -name something, -mtime value, etc., all specify restrictions (i.e., exclusions) to the search.