0

This question already has an answer here:

I am attempting to write a bash script that operates on each directory in a subset. Unfortunately the path contains spaces, and I am unable to change the name.

The for loop insists on breaking at each space; I have tried dozens of variants, but am unable to come up with a solution.

A simplified version is below.

#!/bin/bash
SOURCE="/Volumes/Time Machine Backups/Backups.backupdb/Zaphod"
for file in `ls -d "$SOURCE"/201*`
do
    echo "File: $file"
done

Can anyone suggest how I can get every entry e.g. /Volumes/Time Machine Backups/Backups.backupdb/Zaphod/2017-06-30-215735 in a separate variable.

marked as duplicate by Gilles bash Jul 6 '17 at 22:52

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

0

If no spaces in files in directory:

#!/bin/bash
SOURCE="/Volumes/Time Machine Backups/Backups.backupdb/Zaphod"
cd "$SOURCE"
for file in $(ls -d ./201*)
do
    echo "File: $file"
done

if unsure about spaces being in the directory list or not, do this instead:

#!/bin/bash
SOURCE="/Volumes/Time Machine Backups/Backups.backupdb/Zaphod"
cd "$SOURCE"
shopt -s nullglob
for filename in 201*;do
   if [[ ! -d "$filename" ]];then
      echo "$filename"
   fi
done
shopt -u nullglob

I'm not clear if you want directory file names or not, if not, this is what works.

The second is the generally preferred solution when you don't know if there are spaces or not I believe.

  • Thanks. I had tried this, but realised I needed sudo to cd – Milliways Jul 6 '17 at 3:12
  • 1
    Probably you should quote the cd "$SOURCE". And, of course, `"$filename". It is a good practice to quote expansions, specially if the do contain spaces. – Arrow Jul 6 '17 at 5:24
  • cd $SOURCE doesn't work, you'd need cd "$SOURCE". And parsing ls only works if the files in that directory don't contain any special characters. Don't parse the output of ls and put double quotes around variable substitutions. – Gilles Jul 6 '17 at 22:54
  • thanks for the reminder on the quotes for $SOURCE. However, since I was pretty explicitly clear about the problem with using ls re spaces, and gave the preferred solution noting it's the preferred solution, it's hard to make sense of the rest of your comment. – Lizardx Jul 6 '17 at 23:35
2

The least change solution is:

#!/bin/bash
SOURCE="/Volumes/Time Machine Backups/Backups.backupdb/Zaphod"
for file in "$SOURCE"/201*
do
    echo "File: $file"
done

An alternative (if you have no problem on changing the positional parameters):

#!/bin/bash
SOURCE="/Volumes/Time Machine Backups/Backups.backupdb/Zaphod"
set -- "$SOURCE"/201*
for file; do
    echo "File: $file"
done

A more precise solution that avoids directories and works on file with spaces (but not newlines):

ls -dp "$a"/201* | grep -v '/$' | 
    while read f; do echo "File:$f"; done

Or a solution that works for any name, but that also may list dot-files (if the name match):

find "$a" -type f -name "201*" -exec echo "File: {}" \;

Not the answer you're looking for? Browse other questions tagged or ask your own question.