rrdtool xport filename with spaces - bash

I'm trying to call rrdtool xport command on arbitrary number of files, so I'm writing a script that reads in the rrd file names and builds the DEF argument. The problem is some of the rrd files have whitespaces in them, i.e. "foo bar.rrd" (-_-)...and when the DEF argument is generated, it looks something like this:
DEF:a=foo bar.rrd:sum:AVERAGE
and when this is passed in to the rrdtool command, it generates an error saying "problems reading database name". I also have tried inserting the escape character ("\") before whitespace so it would look like "foo\ bar.rrd", but when this is run in bash, it still produces same error, whereas when I echo the command and copy paste it on the prompt and run it then it works fine...

Just put quotes around the whole thing
"DEF:a=foo bar.rrd:sum:AVERAGE"
rrdtool should be fine with the spaces.

Related

Script is not running the command I wish

Wondering if anyone here can help with this problem. I have custom profiles for certain games that I wish to run but having problems.
In this example, I have a mega drive profile, and a mortal kombat profile.
Below is my runcommand-onstart.sh file. I got some of the code from someone else I found here I think, but have made changes as it didn’t work for me. The script outputs to a log for test purposes. The text output to the log is correct, but doesn’t do what it should, see below:
#!/usr/bin/env bash
# Get system name
system=$1
emulator=$2
rom=$3
command=$4
# rom_bn receives $rom excluding everything from the first char to the last slash '/'
rom_bn="${rom##*/}"
# rom_bn receives $rom_bn excluding everything from the last char to the first dot '.'
rom_bn="${rom_bn%.*}"
rom_joined='"'$rom_bn'"'
# Write to Runcommand Log to test
echo emitter LoadProfileByEmulator "$rom_joined" $1 >> $HOME/start.log
emitter LoadProfileByEmulator "$rom_joined" $1
The command I wish to run is:
emitter LoadProfileByEmulator "Mortal Kombat (World)" megadrive
The test log has the following line:
emitter LoadProfileByEmulator "Mortal Kombat (World)" megadrive
But ledspicer loads the megadrive profile… like it can't read the "Mortal Kombat" bit.
If I copy and paste that line from the log into terminal, ledspicer loads the Mortal Kombat profile as it should….
Many thanks for any help
Quotes aren't processed in the expansion of variables, so when you add quotes to $rom_joined, those are being treated literally. But since the profile doesn't actually have quotes in its name, that doesn't work.
Just quoting the variable in the argument to emitter is enough to make it a single word. If you want the quotes in the log, do that in the echo command.
#!/usr/bin/env bash
# Get system name
system=$1
emulator=$2
rom=$3
command=$4
# rom_bn receives $rom excluding everything from the first char to the last slash '/'
rom_bn="${rom##*/}"
# rom_bn receives $rom_bn excluding everything from the last char to the first dot '.'
rom_bn="${rom_bn%.*}"
# Write to Runcommand Log to test
echo "emitter LoadProfileByEmulator '$rom_joined' '$system'" >> $HOME/start.log
emitter LoadProfileByEmulator "$rom_bn" "$system"

Dynamically generating the filename for svn status output

I have a chef-infra set-up with chef-node as a windows server. The cookbook (recipe) is trying to take the status of the svn working copy folder and write it in a file. The nomenclature of the output file is CHEFRPT_TESTREPO_ddmmyyyy hh:mm:ss.txt. However, the following code is failing to generate the desired
filename with date and time dynamically.
Following is the ruby code of the recipe:
time = Time.now
execute 'stat' do
cwd 'D:\inetpub\TEST_APP'
command 'svn status > D:\SVN_CHECKOUT\REPORTS\CHEFRPT_TESTREPO_#{time.strftime("%Y-%m-%d%H:%M:%S")}.txt'
end
Need some help regarding the variable to be appended at the end of the file to generate the filename with current date and time when it was generated.
Thank You!
You have to use double quotes " instead of your single quotes ' if you want to to interpolate code within a string with #{...}.
As you use single quotes in the command argument, this interpolation will not be performed and the string will be used as is (that is, including the #{time.stftime...} code in the string.
Your final resource should thus look like this:
time = Time.now
execute 'stat' do
cwd 'D:\inetpub\TEST_APP'
command "svn status > D:\\SVN_CHECKOUT\\REPORTS\\CHEFRPT_TESTREPO_#{time.strftime("%Y-%m-%d%H:%M:%S")}.txt"
end
See https://ruby-doc.org/core/doc/syntax/literals_rdoc.html#label-Strings for details about String literal syntax in Ruby.
This issue is coming up because file/folder names in Windows cannot have the colon (:) character. Try manually creating a file though UI or command line. Also see naming a file for the list of special characters that render the filename invalid.
Since we are creating a timestamp with time.strftime("%Y-%m-%d%H:%M:%S"), execute block is failing. Changing %H:%M:%S to some other accepted character should be enough.
Also, as #Holger Just pointed out in his answer, we need to use double quotes to interpolate the value of time.strftime.
In the example below I've used hyphen (-), i.e. %H-%M-%S:
execute 'stat' do
cwd 'D:\inetpub\TEST_APP'
command "svn status > D:\SVN_CHECKOUT\REPORTS\CHEFRPT_TESTREPO_#{time.strftime("%Y-%m-%d%H-%M-%S")}.txt"
end

Bash script sourcing config file but can't use vars in arithmetic

This is killing me. I have a config file, "myconfig.cfg", with the following content:
SOME_VAR=2
echo "I LOVE THIS"
Then I have a script that I'm trying to run, that sources the config file in order to use the settings in there as variables. I can print them out fine, but when I try to put one into a numeric variable for use in something like a "seq " command, I get this weird "invalid arithmetic operator" error.
Here's the script:
#!/bin/bash
source ./myconfig.cfg
echo "SOME_VAR=${SOME_VAR}"
let someVarNum=${SOME_VAR}
echo "someVarNum=${someVarNum}"
And here's the output:
I LOVE THIS
SOME_VAR=2
")syntax error: invalid arithmetic operator (error token is "
someVarNum=
I've tried countless things that theoretically shouldn't make a difference, and, surprise, they don't. I simply can't figure it out. If I simply take the line "SOME_VAR=2" and put it directly into the script, everything's fine. I'm guessing I'll have to read in the config file line by line, split the strings by "=", and find+create the variables I want to use manually.
The error is precisely as indicated in a comment by #TomFenech. The first line (and possibly all the lines) in myconfig.cfg is terminated with a Windows CR-LF line ending. Bash considers CR to be an ordinary character (not whitespace), so it will set SOME_VAR to the two character string 2CR. (CR is the character with hex code 0x0D. You could see that if you display the file with a hex-dumper: hd myconfig.cfg.)
The let command performs arithmetic on numbers. It also considers the CR to be an ordinary character, but it is neither a digit nor an operator so it complains. Unfortunately, it does not make any attempt to sanitize the display of the character in the error message, so the carriage return is displayed between the two " symbols. Consequently, the end of the error message overwrites the beginning.
Don't create Unix files with a Windows text editor. Or use a utility like dos2unix to fix them once you copy them to the Unix machine.

Some symbols don't effect cmd commands while others do

I noticed that cmd seems to accept some characters at the ends of commands. for example all of the following function correctly:
cls.
cls;
cls(
cls\
cls+
cls=
cls\"whatever"
cls\$
cls\#
and these do not:
cls'
cls$
cls)
cls-
cls#
cls\/
Does anybody know why this happens?
Thanks in advance.
It depends on the batch parser.
;,= are general batch delimiters, so you can append/prepend them to the most commands without effect.
;,,= ,=; echo hello
;,cls,;,,
The . dot can be appended to the most commands, as the parser will try to find a file named cls (without extension) cls.exe cls.bat, and when nothing is found then it takes the internal command.
The opening bracket is also a special charcter that the parser removes without error.
The \ backslash is used as path delimiter, so sometimes it works but sometimes you could change even the command.
cls\..\..\..\windows\system32\calc.exe

Bash curl and variable in the middle of the url

I would need to read certain data using curl. I'm basically reading keywords from file
while read line
do
curl 'https://gdata.youtube.com/feeds/api/users/'"${line}"'/subscriptions?v=2&alt=json' \
> '/home/user/archive/'"$line"
done < textfile.txt
Anyway I haven't found a way to form the url to curl so it would work. I've tried like every possible single and double quoted versions. I've tried basically:
'...'"$line"'...'
"..."${line}"..."
'...'$line'...'
and so on.. Just name it and I'm pretty sure that I've tried it.
When I'm printing out the URL in the best case it will be formed as:
/subscriptions?v=2&alt=jsoneeds/api/users/KEYWORD FROM FILE
or something similar. If you know what could be the cause of this I would appreciate the information. Thanks!
It's not a quoting issue. The problem is that your keyword file is in DOS format -- that is, each line ends with carriage return & linefeed (\r\n) rather than just linefeed (\n). The carriage return is getting read into the line variable, and included in the URL. The giveaway is that when you echo it, it appears to print:
/subscriptions?v=2&alt=jsoneeds/api/users/KEYWORD FROM FILE"
but it's really printing:
https://gdata.youtube.com/feeds/api/users/KEYWORD FROM FILE
/subscriptions?v=2&alt=json
...with just a carriage return between them, so the second overwrites the first.
So what can you do about it? Here's a fairly easy way to trim the cr at the end of the line:
cr=$'\r'
while read line
do
line="${line%$cr}"
curl "https://gdata.youtube.com/feeds/api/users/${line}/subscriptions?v=2&alt=json" \
> "/home/user/archive/$line"
done < textfile.txt
Your current version should work, I think. More elegant is to use a single pair of double quotes around the whole URL with the variable in ${}:
"https://gdata.youtube.com/feeds/api/users/${line}/subscriptions?v=2&alt=json"
Just use it like this, should be sufficient enough:
curl "https://gdata.youtube.com/feeds/api/users/${line}/subscriptions?v=2&alt=json" > "/home/user/archive/${line}"
If your shell gives you issues with & just put \&, but it works fine for me without it.
If the data from the file can contain spaces and you have no objection to spaces in the file name in the /home/user/archive directory, then what you've got should be OK.
Given the contents of the rest of the URL, you could even just write:
while read line
do
curl "https://gdata.youtube.com/feeds/api/users/${line}/subscriptions?v=2&alt=json" \
> "/home/user/archive/${line}"
done < textfile.txt
where strictly the ${line} could be just $line in both places. This works because the strings are fixed and don't contain shell metacharacters.
Since you're code is close to this, but you claim that you're seeing the keywords from the file in the wrong place, maybe a little rewriting for ease of debugging is in order:
while read line
do
url="https://gdata.youtube.com/feeds/api/users/${line}/subscriptions?v=2&alt=json"
file="/home/user/archive/${line}"
curl "$url" > "$file"
done < textfile.txt
Since the strings may end up containing spaces, it seems (do you need to expand spaces to + in the URL?), the quotes around the variables are strongly recommended. You can now run the script with sh -x (or add a line set -x to the script) and see what the shell thinks it is doing as it is doing it.

Resources