2

I am struggling to understand why I get different output from the same command run on a single file in Terminal (Mac OS X 10.6.8) and run on more than one file. As I want to run the command in a bash script I am trying to get consistent results when run on one file at a time.

The command giving me the problem

ls -l "filename" | cut -f8 -d' '

I am trying to isolate the file size.

It seems this works for files without extended permissions (eg a first field of "-rw-r--r-- ") but for those with extended permissions (eg a first field of "-rwxrwxrwx@") I need cut -f7 -d' '

Interestingly if I pick a file of each type and run:

ls -l "filename1" "filename2" | cut -f8 -d' '

it returns the filesize for both files without problem. I don't understand why that should happen ... but of course in my script I am doing this one file at a time.

I've tried using sed to removed doubled whitespace and doubled tabs and this does change the field number needed to give the file size but it still seems to give results which are dependent on whether or not their are extended file permissions.

I'm including the while loop from my script for reference but it's not easily read because the file size is only one of 4 colon separated fields I'm inserting.

#!/bin/bash

# lots of other stuff here including specifying input (which is a list of filenames with complete paths) and output files  ...

while IFS= read -r line
do
    echo "$line":`exiftool -all= -o - "$line" | md5`:`md5 "$line" | cut -f2 -d'=' | sed -e 's/^[ \t]*//'`:`ls -l "$line" | cut -f8 -d' '` >> "$outputfile"
done < "$file"

Can anyone help throw some light on this for me?

1 Answer 1

1

The real problem is that you are trying to parse the output of ls. This is never a good idea, and as you observed, may break easily. For once, it's not even portable across operating systems. Parsing ls is often a symptom of needing to do something else but working around it (and that's an XY Problem).

Anyway, you're asking:

I am trying to isolate the file size.

Then simply use wc -c:

wc -c < filename

This will give you the file size in bytes (as opposed to du which gives you blocks). You can trim the whitespace by piping into tr -d ' ' or similar.

As a minor tip for your loop: Instead of using backticks to perform command substitution, do yourself a favor and use $(), e.g. $(md5 "$line" | cut -f2 -d'=' | sed -e 's/^[ \t]*//'). This has various advantages, including increased readability and less headaches when nesting such commands.

1
  • 1
    Thank you. This was really a case of not being able to see the wood for the trees as I was too focused on why it didn't work instead of how to get it to work.
    – yvf5rcuya4
    Apr 11, 2013 at 7:17

You must log in to answer this question.

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