Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!


Click here to return to the 'Re: Script to list all filesystem objects with ACLs' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Re: Script to list all filesystem objects with ACLs
Authored by: mzso on Aug 24, '08 01:39:06PM

You're right: my previous script did only filter the output of find+ls and did not produce a CSV like structure.

Just for the sake of practise, I've created a pure sed variant that really creates CSV output:


#!/bin/sh

tempfile=
if [ -n "$1" ]; then
  target=$1
else
  target=/
fi

if [ -d "${target}" ]; then
  if [ ! -x "${target}" ]; then
    echo "You have no read access to the specified directory."
    exit 1
  else
    tempfilename=find_acls_csv_$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" ").dat
    if [ -d "${TMPDIR}" -a -r "${TMPDIR}" -a -w "${TMPDIR}" ]; then
      tempdir=${TMPDIR}
    else
      if [ -d "${TMP}" -a -r "${TMP}" -a -w "${TMP}" ]; then
        tempdir=${TMP}
      else
        if [ -d "/tmp" -a -r "/tmp" -a -w "/tmp" ]; then
          tempdir=/tmp
        else
          curdir=$(pwd)
          if [ -d "${curdir}" -a -r "${curdir}" -a -w "${curdir}" ]; then
            tempdir=${curdir}
          else
            echo 'Could not find a readable and writable temporary directory.'
            exit 5
          fi
        fi
      fi
    fi
    tempfile=${tempdir}/${tempfilename}
    if touch "${tempfile}"; then
      find "${target}" -exec ls -alde '{}' \; > "${tempfile}" 2> /dev/null
      target=${tempfile}
    else
      echo "Could not write to temporary file at ${tempfile}."
      exit 4
    fi
  fi
else
  if [ -f "${target}" ]; then
    if [ ! -r "${target}" ]; then
      echo "You have no read access to the specified file."
      exit 2
    fi
  else
    echo "The specified target path does not exist."
    exit 3
  fi
fi

if [ -n "${tempfile}" -a $(id -u) -ne 0 ]; then
  echo '"Tip: you might want to run this script as the root user (eg. via sudo)."'
fi
echo '"mode","# of links","owner","group","bytes","month","day","time","path","acls"'
cat "${target}" | sed -Ee '
:a
s#^([^/ ]+) +#\1\#*\##
ta
:b
$! {
N
bb
}
s/[[:cntrl:]]*(\n)/\1/g
:c
s#(\n[^/ ]+) +#\1\#*\##g
tc
s#\n ([0-9]+:[^[:cntrl:]]*)#!*!\1#g
s#(\n)([^[:cntrl:]]*!\*!)#\1!\2#g
s#\n[^!][^[:cntrl:]]*##g
s#\n!#\
#g
s#^([^[:cntrl:]]*!\*!)#!\1#g
s#^[^!][^[:cntrl:]]*\n##g
s#^!##g
s#((^|\n)[^![:cntrl:]]+)!\*!#\1\#*\##g
s#"#""#g
s#(.+)#"\1"#
s#\#\*\##","#g
s#\n#"&"#g
s#!\*!#\
#g
'
if [ -n "${tempfile}" ]; then
  rm "${tempfile}"
fi

It seems that the sed in Darwin is not fully following the description of it's manpages. :-( Unfortunately this script turned out to be really slow. It processed my 130MB file listing in several minutes (4-5min).

I've created an Awk script that creates a CSV output as well:


#!/bin/sh

tempfile=
if [ -n "$1" ]; then
  target=$1
else
  target=/
fi

if [ -d "${target}" ]; then
  if [ ! -x "${target}" ]; then
    echo "You have no read access to the specified directory."
    exit 1
  else
    tempfilename=find_acls_csv_$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" ").dat
    if [ -d "${TMPDIR}" -a -r "${TMPDIR}" -a -w "${TMPDIR}" ]; then
      tempdir=${TMPDIR}
    else
      if [ -d "${TMP}" -a -r "${TMP}" -a -w "${TMP}" ]; then
        tempdir=${TMP}
      else
        if [ -d "/tmp" -a -r "/tmp" -a -w "/tmp" ]; then
          tempdir=/tmp
        else
          curdir=$(pwd)
          if [ -d "${curdir}" -a -r "${curdir}" -a -w "${curdir}" ]; then
            tempdir=${curdir}
          else
            echo 'Could not find a readable and writable temporary directory.'
            exit 5
          fi
        fi
      fi
    fi
    tempfile=${tempdir}/${tempfilename}
    if touch "${tempfile}"; then
      find "${target}" -exec ls -alde '{}' \; > "${tempfile}" 2> /dev/null
      target=${tempfile}
    else
      echo "Could not write to temporary file at ${tempfile}."
      exit 4
    fi
  fi
else
  if [ -f "${target}" ]; then
    if [ ! -r "${target}" ]; then
      echo "You have no read access to the specified file."
      exit 2
    fi
  else
    echo "The specified target path does not exist."
    exit 3
  fi
fi

if [ -n "${tempfile}" -a $(id -u) -ne 0 ]; then 
  echo '"Tip: you might want to run this script as the root user (eg. via sudo)."'
fi
echo '"mode","# of links","owner","group","bytes","month","day","time","path","acls"'
awk '
{
  if (match($0, "^ [0-9]+:") > 0) {
    acls++
    gsub("^ +", "", $0);
    if (acls > 1) {
      buffer = buffer "\n" $0
    }
    else {
      buffer = buffer ",\"" $0
    }
  }
  else {
    if (buffer != "" && acls > 0) {
      print buffer "\""
    }
    acls = 0
    buffer = ""
    for (i = 1; i <= 8; i++) {
      gsub("\"", "\"\"", $i)
      buffer = buffer "\"" $i "\","
    }
    path = substr($0, index($0, $8) + 5)
    sub("^ +", "", path)
    gsub("\"", "\"\"", path)
    buffer = buffer "\"" path "\""
  }
}' "${target}"

if [ -n "${tempfile}" ]; then
  rm "${tempfile}"
fi
This one processed the 130MB file listing in 20 seconds. The output is a comma separated file where multiple ACLs are kept in a single field (spreadsheet cell).

[ Reply to This | # ]