2013-07-28 2 views
4

Мне нужна помощь с использованием xargs (1) и bc (1) в той же строке. Я могу сделать это несколько строк, но я действительно хочу найти решение в одной строке.Почему bc и args не работают вместе в одной строке?

Вот проблема: следующая строка напечатает размер file.txt

ls -l file.txt | cut -d" " -f5 

И следующая строка напечатает 1450 (очевидно, 1500 - 50)

echo '1500-50' | bc 

Попытка чтобы добавить эти два вместе, я делаю это:

ls -l file.txt | cut -d" " -f5 | xargs -0 -I {} echo '{}-50' | bc 

пр. oblem, это не работает! :)

Я знаю, что xargs, вероятно, не является правильной командой для использования, но это единственная команда, которую я могу найти, кто может позволить мне решить, где поставить аргумент, который я получаю из канала.

Это не первый случай, когда у меня возникают проблемы с этой проблемой. Это будет большая часть помощи ..

Благодаря

ответ

1

Если вы делаете

ls -l file.txt | cut -d" " -f5 | xargs -0 -I {} echo '{}-50' 

вы увидите этот вывод:

23 
-50 

Это означает, что bc не видит полное выражение.

Просто используйте -n 1 вместо -0:

ls -l file.txt | cut -d" " -f5 | xargs -n 1 -I {} echo '{}-50' 

и вы получите

23-50 

который bc будет обрабатывать счастливо:

ls -l file.txt | cut -d" " -f5 | xargs -n 1 -I {} echo '{}-50' | bc 
-27 

Так что ваша основная проблема в том, что -0 ожидает не линии но \0 завершенные строки. И, следовательно, новая строка (и) предыдущих команд в трубе искажает выражение bc.

+0

Лучше знать мои ошибки, чтобы получить альтернативу :) – winter

1

Это может работать для вас:

ls -l file.txt | cut -d" " -f5 | sed 's/.*/&-50/' | bc 

Infact вы можете удалить разрез:

ls -l file.txt | sed -r 's/^(\S+\s+){4}(\S+).*/\2-50/' | bc 

Или использовать AWK:

ls -l file.txt | awk '{print $5-50}' 
+0

Спасибо, человек не знал о замене шаблона '&'. – winter

1

Разбор вывода команды ls - не самая лучшая идея. (действительно).

вы можете использовать множество других решений, такие как:

find . -name file.txt -printf "%s\n" 

или

stat -c %s file.txt 

или

wc -c <file.txt 

и можете использовать Баш арифметик, для избежания ненужных медленных вил процесса, как :

find . -type f -print0 | while IFS= read -r -d '' name 
do 
     size=$(wc -c <$name) 
     s50=$(($size - 50)) 
     echo "the file=$name= size:$size minus 50 is: $s50" 
done 
1

Вот еще одно решение, которое используют только одну внешнюю команду: stat:

file_size=$(stat -c "%s" file.txt) # Get the file size 
let file_size=file_size-50   # Subtract 50 

Если вы действительно хотите, чтобы объединить их в одну строку:

let file_size=$(stat -c "%s" file.txt)-50 

Команда stat получает вам файл размер в байтах. Синтаксис выше для Linux (я тестировал Ubuntu). На Mac синтаксис немного отличается:

let file_size=$(stat -f "%z" mini.csv)-50 
Смежные вопросы