1

I'm trying to record the size of the compressed build file using Fastlane in my CICD pipeline. If I try this in the command line:

du -h fileName.ipa | awk '{print $1}'

it works fine. However, if I try to put it in my script, like so:

sh '''
  # Add filesize to release message

var fileName=cat '"#{IPA_FILE_NAME_FILE}"' fileSizeInfo=(du -h '"#{IPA_FILE_PATH}"'$fileName | awk '{print $1}') echo "$buildInfo" sed -i -e "s|FILESIZE_INFO|'"$fileSizeInfo"'|g" '"#{RELEASE_MESSAGE_HTML_FILE_NAME}"' '''

it gives me these syntax errors:

[17:50:24]:     262:          var fileName=`cat '"#{IPA_FILE_NAME_FILE}"'`
[17:50:24]:  => 263:          fileSizeInfo=(du -h '"#{IPA_FILE_PATH}"'$fileName | awk '{print $1}')
[17:50:24]:     264:          echo "$buildInfo"
[17:50:24]:     265:          sed -i -e "s|FILESIZE_INFO|'"$fileSizeInfo"'|g" '"#{RELEASE_MESSAGE_HTML_FILE_NAME}"'
[!] Syntax error in your Fastfile on line 263: Fastfile:263: syntax error, unexpected '{', expecting `end'
..._FILE_PATH}"'$fileName | awk '{print $1}')
...                              ^
Fastfile:285: syntax error, unexpected `end', expecting end-of-input
    end
    ^~~

I'm kind of a newbie to shell scripting, so any help is appreciated - I probably just have some quotes in the wrong place or something. If it helps, Fastlane uses Ruby syntax, so that's Ruby string interpolation in there.

Edit:

Here's the whole lane I'm calling in my fastfile, for more context:

# Send message MS Teams Channel
    lane:sendTeamsMessage do |options|
=begin
  MS Teams messages are sent using webhooks and it got limited support to HTML and Markdown. 
  This implementation uses HTML formatted message.
  Webhook will not accept new lines or double quotes because it can break the JSON struture.
  The message file preparation is done in multiple steps.
  1. Add .ipa file size info to release message HTML
  2. Replace all double quotes with single quotes  
  3. Copy the Teams message payload template and update it with the message content
  4. Replace 'MESSAGE_INFO' string with the HTML formatted content file
  5. Send the message to Teams channel
=end
      sh '''
      # Add filesize to release message
  var fileName=`cat '"#{IPA_FILE_NAME_FILE}"'`
  var fullFilePath='"#{IPA_FILE_PATH}"'$fileName
  echo fullFilePath
  fileSizeInfo=(du -h $fullFilePath | awk '{print $1}')
  echo "$buildInfo"
  sed -i -e "s|FILESIZE_INFO|'"$fileSizeInfo"'|g" '"#{RELEASE_MESSAGE_HTML_FILE_NAME}"'
  '''

  sh '''
  # Copy the release message html file
  cp -fr '"#{RELEASE_MESSAGE_HTML_FILE_NAME}"' '"#{TEAMS_MESSAGE_FILE_NAME}"'
  '''
  # Replace all double quotes with single quotes to make it JSON friendly
  sh("sed","-i","-e","s|\"|\'|g","#{TEAMS_MESSAGE_FILE_NAME}")

  sh'''
  cp -fr '"#{TEAMS_PAYLOAD_TEMPLATE_FILE_NAME}"' '"#{TEAMS_PAYLOAD_FILE_NAME}"'
  message=`cat '"#{TEAMS_MESSAGE_FILE_NAME}"'`
  sed -i -e "s|MESSAGE_INFO|'"$message"'|g" '"#{TEAMS_PAYLOAD_FILE_NAME}"'
  '''
  # Send the message to Teams channel
  sh '''
  echo '"#{options[:webhook]}"'
  curl -H "Content-Type: application/json" -d @'"#{TEAMS_PAYLOAD_FILE_NAME}"' '"#{options[:webhook]}"'
  '''
end

I tried moving the filepath/filename out to its own variable, but I'm still getting the same issue.

  • I think the problem is with where you put your sh '''… code, not with the code itself. But: you don't explain where you put that. – Marcus Müller Sep 06 '23 at 14:15
  • 1
    Beware that du gives the 'size on disk' of the file - which may be either more or less than the 'size' of the file, depending on block size and sparse files and the like.

    If you want to know how many bytes long the file is, the most portable way is to use stat --format %s <filename>.

    – Popup Sep 06 '23 at 14:19
  • 1
    @Kusalananda the lack of space is intentional - I don't want a space between the path to the file and the file name. The #{} is ruby string interpolation (I think - I'm not super familiar with ruby syntax either, so Fastlane may be doing its own thing here.) – KDBartleby Sep 06 '23 at 14:30
  • @Popup does that give a human readable format? I tried using stat, but just printing out the number of bytes isn't super helpful when I'm trying to send an informational message. – KDBartleby Sep 06 '23 at 14:31
  • 1
    https://shellcheck.net/ can help with syntax issues – Chris Davies Sep 06 '23 at 14:38
  • 1
    The error is from Fastfile, which I guess is some Ruby thing from the tags, so IMO this should be asked on [so] where someone with Ruby expertise can help with embedding the shell script in Ruby. Also: why do this processing in the shell script instead of getting the du output and processing that in Ruby directly to create your message? – muru Sep 06 '23 at 14:41
  • 1
    Fully agreeing with Muru: As said in my first comment, the problem is with how you embed this in the rest of your code, not with the shell script itself. It's ruby complaining about the syntax, not your shell! Also, you're using ruby: why run a shell script to get the size of a file? I bet there's ruby built-in functionality that does things – Marcus Müller Sep 06 '23 at 14:59
  • Hello and welcome to unix.se. I upvoted your question as it contains all the steps you tried, and lots of context, which is always good to do. I don't understand why it was at '0' where there were several answerers (maybe some people downvoted it? but it seems harsh, as you showed proper research and context) – Olivier Dulac Sep 13 '23 at 08:14
  • note: in bash : '''foo''' is (almost) equivalent for the shell to the usual: 'foo'. as '' will be seen as empty string, the shell will interpret the first ''' as "entersinglequote, exitsinglequote, entersinglequote", ie '. [to be thorough: it is still different than no string at all, for ex: script.bash '' have 1 (empty) $1 argument ($# is 1), whereas script.bash have 0 argument($# is 0). I am unsure if your ways isn't good after all : it does add visibility! I'll wait for better persons than me (StephaneChazelas, Terdon, et) to weigh-in on this and possible pbs... – Olivier Dulac Sep 13 '23 at 08:27

3 Answers3

2

The bash idiom for catching the output from commands like:

du -h fileName.ipa | awk '{print $1}'

and saving the output into a variable is:

fileSizeInfo=$(du -h fileName.ipa | awk '{print $1}')

This is very similar to a line you have in the Bash part of your script, except your code is missing the $ before the (. This seems likely to be a main cause for the confusing output you're getting.

Sotto Voce
  • 4,131
1

It seems, you want to try a command substitution.

In your example you have

var fileName=`cat '"#{IPA_FILE_NAME_FILE}"'`

as an valid command substitution.

Your second command substitution fails because of the missing $. It's should look like

fileSizeInfo=$(du -h $fullFilePath | awk '{print $1}')

The available two command substitutions in bash are the modern POSIX style

$(command)

or the older style

`command`

It's recommended to use the first one, by the way it's increase readability.

If you want to make your code more readable, try to code like you speak. Another way to get the file size in a more readable way without a pipe and another command could be

stat -c "%s" /path/to/file

In your example you could try

fileSizeInfo=$(stat -c "%s" $fullFilePath)
0

In Ruby you can use:

File.stat("/path/to/file").size
dinoex
  • 26