Why don't bc and args work together on the same line?

I need help using xargs (1) and bc (1) on the same line. I can do this a few lines, but I really want to find a solution on a single line.

Here is the problem: The next line will print the file.txt size

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

And the next line will print 1450 (which is obviously 1500 - 50)

 echo '1500-50' | bc 

Trying to add these two together, I do this:

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

The problem is that it does not work! :)

I know that xargs is probably not the right command to use, but it is the only command I can find who can let me decide where to put the argument that I get from the channel.

This is not the first time I have problems with such a problem. It will be a big help ..

thanks

+4
source share
4 answers

If you do

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

you will see this output:

 23 -50 

This means that bc does not see the full expression.

Just use -n 1 instead of -0 :

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

and you will get

 23-50 

which bc will be processed happily:

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

So your main problem is that -0 does not expect lines, but \0 complete lines. And therefore, the new line (s) of the previous commands in the pipe distorts the expression bc.

+1
source

This might work for you:

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

Infact you can remove the cut:

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

Or use awk:

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

Analyzing the output from the ls is not a good idea. (Actually).

you can use many other solutions, for example:

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

or

 stat -c %s file.txt 

or

 wc -c <file.txt 

and can use bash arithmetic to avoid unnecessary slow process forks, for example:

 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
source

Here is another solution that uses only one external command: stat :

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

If you really want to combine them in one line:

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

The stat command gets the file size in bytes. The syntax above is for Linux (I tested Ubuntu). On Mac, the syntax is slightly different:

 let file_size=$(stat -f "%z" mini.csv)-50 
+1
source

Source: https://habr.com/ru/post/1493901/


All Articles