1

From my local server I only have access to stfp to a remote server where I want to check the size of my backup file as it's being created. So I've been able to write a bit of bash that logs in and issues an 'ls -l' command:

file_listing=$(sftp connection_string:Path/to <<<$'ls -l file.sql.gz')

...which produces:

$ echo $file_listing
Changing to: /Path/to sftp> ls -l file.sql.gz -rw------- ? 19009 19009 7834147822 Oct 19 23:02 file.sql.gz

And I want to be able to use either bash native string manipulation or grep or something just to extract the file size part of that string. In this case the 7834147822

I've tried grepping, and egrepping for a pattern

size_pattern='([0-9]{1} {1}[0-9]+ {1}[A-Z]{1})'

or doing...

echo $file_listing  | egrep -o '[[:digit:]]\{1\}[[:blank:]][[:digit:]]\+[[:blank:]][A-Z]\{1\}'

...or something. I realise that would give me "9 7834147822 O" if it worked, but I reckon even I can manage string manipulation to strip one character and one space from either end before using it as a file size.

Does that make sense? Anyone got some thoughts?

Best wishes, Jock Coats

2
  • I tried stat on the remote sftp command line and got command not found. Nor can I break out into an ssh session. And I don't even think paramiko will work because I seemed to understand that it started with an ssh session before spawning an sfto session so that wouldn't work.
    – Jock Coats
    Oct 20, 2022 at 13:17
  • Yeah, sorry, if you only have sftp you can't run stat, that's why I deleted my comment.
    – terdon
    Oct 20, 2022 at 13:29

3 Answers 3

2

If you don't quote your variable with echo, it all is printed in one line. Put quotes, and it will be easier for you to grep.

However, I would still prefer awk:

echo "$file_listing"  | awk 'NR==3{print $5}'

Another interesting approach using set:

set -- $(tail -n1 <<< "$file_listing")
echo $5

Note, instead of parsing ls -l, it would be better to use stat if you have access via ssh, not only sftp:

ssh user@server 'stat --format %s /path/to/file'
12
  • TBH I was trying to stick with grep just because I didn't fancy grokking another "language" in the form of awk. But that works beautifully, thank you - apparently I can't yet give an uptick but it deserves one.
    – Jock Coats
    Oct 20, 2022 at 13:05
  • I think there's only one line, not 3. It was your (helpful!) edit that made it look like three lines.
    – terdon
    Oct 20, 2022 at 13:05
  • @JockCoats wait, you have three lines in the $file_listing variable? Also, if this worked for you, you can accept it by clicking on the checkmark on the left. That is the best way to express your thanks on the Stack Exchange sites.
    – terdon
    Oct 20, 2022 at 13:07
  • Changing to ... , > sftp and the result are three lines in the variable. I checked that... ;-)
    – pLumo
    Oct 20, 2022 at 13:07
  • Can we pelase edit the question to show that then? Otherwise it's a bit confusing.
    – terdon
    Oct 20, 2022 at 13:08
1

If you do not like awk, you can use a combination of standard tools:

These two commands are equivalent:

echo "$file_listing"  | awk 'NR==3{print $5}'
echo "$file_listing"  | head -n3 | tail -n1 | tr -s ' ' '\t' | cut -f5
  • head and tail will print first 3 lines, and just last line of the these three.
  • tr will squeeze all repeated spaces and replace them with a tab.
  • And the cut will print 5th word.
0
0

AWK is your friend here. AWK will look at a line of text and separate it into columns based on the white space it encounters. Each one of those columns has a numeric place holder $1, $2, etc. On my machine ls -l produces 9 columns, and this command will get what you need.

ls -l file.sql.gz | awk '{print $5}'

If you want the human readable size in K / MB / GB use ls -lh

In your example the line of text also contains info like 'Changing to: ...' You can see the entire line that AWK is receiving with awk '{print $NF}' and then simply count the columns until you get to the one you're looking for.

2
  • TBH I was trying to stick with grep just because I didn't fancy grokking another "language" in the form of awk. And, just to note, I can't send that command string as one to the sftp session - I need to send ls -l to the sftp and then get its output into the local buffer on the machine from which I'm running the command. But when I do it as pLumbo suggests below on the returned string it works perfectly.
    – Jock Coats
    Oct 20, 2022 at 13:07
  • It is best to put the code in code formatted blocks. It looks like you started with the ` before ls, but you need one at the end also. Oct 31, 2022 at 15:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .