multipleinterfaces
multipleinterfaces

Reputation: 9173

How do I use awk to prepend a directory to a list of files in a variable?

#!/bin/bash
FILES='a.txt
b.txt
c.txt'
OUT_FILES=$(awk -F ' ' \$0=\"foo/bar/\"\$0 <(echo ${FILES}))

echo ${OUT_FILES}

In the above script, I expect a list of files in ${OUT_FILES} as foo/bar/a.txt foo/bar/b.txt foo/bar/c.txt, but the output is foo/bar/a.txt b.txt c.txt. Later on, the ${OUT_FILES} list is provided to another command with xargs. What is wrong with the awk expression that results in only prepending the path to the first element of the list?

Upvotes: 0

Views: 176

Answers (2)

karakfa
karakfa

Reputation: 67567

quotes are missing, also will be cleaner this way.

$ awk '{print "foo/bar/" $0}' <<< "$FILES"
foo/bar/a.txt
foo/bar/b.txt
foo/bar/c.txt

perhaps easier with sed

$ sed 's_^_foo/bar/_' <<< "$FILES"
foo/bar/a.txt
foo/bar/b.txt
foo/bar/c.txt

Upvotes: 4

glenn jackman
glenn jackman

Reputation: 247210

Using an array would be a much much better way to store the filenames:

dirname="/tmp/foo"
files=( a.txt b.txt c.txt )
out_files=( "${files[@]/#/$dirname/}" )

Let's see what those arrays now contain:

$ declare -p files out_files dirname
declare -a files='([0]="a.txt" [1]="b.txt" [2]="c.txt")'
declare -a out_files='([0]="/tmp/foo/a.txt" [1]="/tmp/foo/b.txt" [2]="/tmp/foo/c.txt")'

"${files[@]/#/$dirname/}" is a fairly tricky parameter expansion:

  • ${parameter/pattern/string} replaces the first occurrance of pattern with the given string
    • if pattern starts with #, then the match will be anchored to the beginning of the value of $parameter
    • so I'm matching the empty string at the start of the value, and replacing that empty string with the value of $dirname and a literal slash
  • if parameter is an array expansion, then the pattern replacing will occur for each element of the array.

Another point to note, don't use ALLCAPS_VARNAMES: it's too easy to over-write crucial shell variables (like $PATH).

Upvotes: 2

Related Questions