user100464
user100464

Reputation: 18429

bash: fill file from another file

I have a file named SOURCE, and I want to create a file named TARGET of a specific length, containing copies of SOURCE. TARGET's length is not necessarily an integer multiple of SOURCE's length. I want to do this using bash on Linux.

My first try was this:

while true; do cat SOURCE; done | head -c $TARGET_LENGTH > TARGET

That hangs after writing the specified number of bytes to TARGET. How do I make it not hang? (I suspect I'm missing a detail around how pipes and signals work.)

Edit: I know that while true runs forever, but I expected the head command to shut everything down after consuming the specified number of bytes.

Upvotes: 3

Views: 256

Answers (3)

Ryan Groten
Ryan Groten

Reputation: 208

You need to break out of the while loop.

For example, using a temp file, fill it until it's the same size or larger than your target length, then break out of the loop and use head -c to output the temp file into your target gile.

while true; do 
  cat $SOURCE_FILE >> /tmp/temp.out; 
  TMP_LENGTH=$(wc -c /tmp/temp.out |awk '{print $1}')
  if [ $TMP_LENGTH -ge $TARGET_LENGTH ]; then 
    break
  fi
done
head -c $TARGET_LENGTH /tmp/temp.out > $TARGET_FILE

Upvotes: 0

gniourf_gniourf
gniourf_gniourf

Reputation: 46833

How about this?

while cat SOURCE; do true; done | head -c "$TARGET_LENGTH" > TARGET

Upvotes: 6

justAnotherUser
justAnotherUser

Reputation: 181

Here's a longwinded solution... Can someone do something more elegant?

echo > $TARGET
sourceLength=`wc -c $SOURCE | awk '{print $1}'`
let loops=$(( $TARGET_LENGTH/$sourceLength ))

let n=0;
while [ $n -lt $loops ]; do
  let n=$(( $n+1 )) || exit 1
  cat $SOURCE >> $TARGET
done

let mod=$(( $TARGET_LENGTH % $sourceLength ))
head -c $mod $SOURCE >> $TARGET

Upvotes: 1

Related Questions