2015-02-20 2 views
3

У меня есть файл с именем SOURCE, и я хочу создать файл с именем TARGET определенной длины, содержащий копии SOURCE. Длина TARGET не обязательно является целым числом, кратным длине SOURCE. Я хочу сделать это, используя bash для Linux.bash: заполнить файл из другого файла

Моя первая попытка была такова:

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

Это висит после записи указанного количества байтов в TARGET. Как заставить его не повесить? (Я подозреваю, что я пропускаю деталь вокруг, как трубы и сигналы работы.)

Edit: Я знаю, что while true бежит навсегда, но я ожидал, что команда голову, чтобы закрыть все вниз после употребления указанного количества байтов.

+1

'while true; делать ...; done' будет выполняться навсегда. Вы должны сказать 'while', когда и как остановиться. – fedorqui

+0

'while true' работает вечно ... И команда' head' ничего не знает о существовании 'while' перед ним, поэтому не может« закрыть все ». Я бы, наверное, использовал что-то вроде 'awk' для этого. – lurker

+1

Если вы хотите действительно смешное решение (но эй, это шуточное решение, не используйте его серьезно): 'yes '$ ( TARGET'. –

ответ

6

Как насчет этого?

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

Спасибо, это именно то, что я искал. – user100464

+3

Я думаю, что это то, что происходит: головные выходы, которые закрывают свой stdin, а затем кошка выходит с ненулевым кодом выхода, потому что его stdout закрывается, что завершает цикл. – user100464

+0

@ пользователь100464 это правильно! –

0

Вам нужно вырваться из цикла while.

Например, используя временный файл, залейте его до тех пор, пока он не будет иметь тот же размер или больше вашей целевой длины, а затем вырвется из цикла и используйте head -c для вывода временного файла в ваш целевой уровень.

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 
1

Вот долговременное решение ... Может ли кто-нибудь сделать что-то более элегантное?

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 
+0

'head -c 0' делает правильную вещь, поэтому вам не нужно' || exit 1'. И, возможно, замените первый цикл на что-то вроде 'for i в $ (seq 1 $ loops); do cat $ SOURCE; сделано> $ TARGET'. Если вы это сделаете, вы также можете устранить эхо в начале. – user100464

+0

yup, это хорошие предложения. '|| exit 1' является нерешительным от отладки опечатки. Я надеюсь, что кто-то может придумать один-лайнер вместо этого цикла. – justAnotherUser

Смежные вопросы