In bash 3.2 (default on the recent macOS), running printf "-1" gives me some error like this:
bash: printf: -1: invalid option
Which I have no problem in zsh, indeed, a leading hyphen in any string passed to printf will trigger that error. shellcheck has not warning for this. Also tried echo "-1" and seems fine.
I know the error is avoidable by using printf "%s" "-1", but can someone explain the reason behind it? thanks.
For utilities that conform to the standard syntax (echo being a notable exception), leading operands starting with - indicate options. Operands are treated as options even if the command does not provide options by those names, causing the error message you've seen. An explicit end of the options can be indicated with --: printf -- -1 will cause the string -1 to be interpreted as the format string and printed.
I am trying to write a short script that will take two command line parameters as file extensions and change all files with the first extension to have the second extension. I am pretty sure the following script should work but for some reason it gives me a syntax error on the line where the variable name is defined and I am not sure why. I am rather new to bash scripting so any help would be greatly appreciated!
for f in "*$1" do
name=${f%.*}
mv $f "$name$2"
done
The error message printed by Bash looks like:
./script: line 4: syntax error near unexpected token `name=${f%.*}'
./script: line 4: `name=${f%.*}'
The reason is that you are missing a ; or newline before do. Also you don't want to quote * in "*$1", since the * will be taken as a literal. Corrected script:
#!/usr/bin/env bash
for f in *"$1"; do
name=${f%.*}
mv "$f" "$name$2"
done
I'm probably missing something very basic. I have a web script that tells a shell script to update some database records. These records are for statistics, and this way the web script does not have to wait while the database records are updated. However, I can't actually make the shell script work running it from commandline. Here is the code that I'm trying:
perl async_sql.pl 'UPDATE some_table set i = i + 1 WHERE (n in (\'328430\',\'334969\',\'330179\',\'335290\',\'335285\',\'335284\',\'335264\',\'335145\',\'335146\',\'335147\',\'335148\',\'335149\',\'335230\',\'335201\',\'335198\',\'335196\',\'335167\',\'335151\',\'335152\',\'335143\',\'334969\',\'334972\',\'334977\',\'334978\',\'334979\',\'334980\',\'334982\',\'334983\',\'334984\',\'334934\',\'334947\',\'334948\',\'334950\',\'334992\',\'335014\',\'335026\',\'335030\',\'335032\',\'334864\',\'334862\',\'334861\',\'334858\',\'334855\',\'334852\',\'334850\',\'334849\',\'334848\',\'334847\',\'334844\',\'334842\'))'
Bash tells me:
-bash: syntax error near unexpected token `)'
What am I missing?
It is not possible to escape single quote in single quotes. Use " " instead
perl async_sql.pl "UPDATE some_table set i = i + 1 WHERE (n in ('328430','334969','330179','335290','335285','335284','335264','335145','335146','335147','335148','335149','335230','335201','335198','335196','335167','335151','335152','335143','334969','334972','334977','334978','334979','334980','334982','334983','334984','334934','334947','334948','334950','334992','335014','335026','335030','335032','334864','334862','334861','334858','334855','334852','334850','334849','334848','334847','334844','334842'))"
Also, there are other ways to deal with this problem:
echo "quote'test"
echo 'quote'"'"'test'
echo 'quote'\''test'
echo $'quote\'test'
All these should print quote'test as a single parameter. Which means that another great solution for your problem is:
perl async_sql.pl $'UPDATE some_table set i = i + 1 WHERE (n in (\'328430\',\'334969\',\'330179\',\'335290\',\'335285\',\'335284\',\'335264\',\'335145\',\'335146\',\'335147\',\'335148\',\'335149\',\'335230\',\'335201\',\'335198\',\'335196\',\'335167\',\'335151\',\'335152\',\'335143\',\'334969\',\'334972\',\'334977\',\'334978\',\'334979\',\'334980\',\'334982\',\'334983\',\'334984\',\'334934\',\'334947\',\'334948\',\'334950\',\'334992\',\'335014\',\'335026\',\'335030\',\'335032\',\'334864\',\'334862\',\'334861\',\'334858\',\'334855\',\'334852\',\'334850\',\'334849\',\'334848\',\'334847\',\'334844\',\'334842\'))'
I have only placed a dollar sign $ right before the parameter. That's it. A dollar sign before single quotes turns on ANSI-C Quoting
bash: syntax error near unexpected token `('
this type of error can be solve by the turn on extended globbing by git bash command is "shopt -s extglob"
I am trying to write a bash-script which will create a certain number of files which are passed into an argument, and also fill that file with relevant information. However, for some reason I can't get it to work properly, and googling turned up nothing.
I want it to create files like the following:
FileName:
Prob_3_ch_17.cpp
Filled as the following:
/*
User: Johnny Smith
Prob: 3
Output:
*/
Where the first command line argument is the chapter number. The second is the starting number, and the third is the ending number. So if the following is ran
sh ../FileMaker.sh 17 1 10
It will make 10 files, each filled with the appropriate data and proper file names, for chapter 17. This is the script that I came up with.
#!/bin/bash
# Syntax:
# $1 = Chapter Number
# $2 = Starting Number
# $3 = Ending Number
CHAPTER=$1
FIRST=$2
LAST=$3
U_NAME="Johnny Smith"
# Name: Prob_$NUMBER_Ch_$1.cpp
for ((NUMBER=$FIRST; $NUMBER<=$LAST; $NUMBER++));
do
if [ -e "Prob_$NUMBER_Ch_$CHAPTER.cpp" ]; then
echo "File Prob_$NUMBER_Ch_$CHAPTER.cpp already exists!"
else
echo "/* \n User: $U_NAME \n Problem: $NUMBER \n Output: \n */" >> "Prob_$NUMBER_Ch_$CHAPTER.cpp"
done
However, it doesn't run. I get the following error:
../FileMaker.sh: line 21: syntax error near unexpected token `done'
../FileMaker.sh: line 21: `done'
I've googled and found other people have had the same problem, but I didn't fully understand what was meant in the solution. Can someone please help me? I'm not the best at shell scripting, and I'm trying to learn by making scripts like this.
Thanks in advanced.
Syntax for if block and for-loop is wrong. correct syntax would be -
for ((NUMBER=FIRST; NUMBER<=LAST; NUMBER++));
do
if [ -e "Prob_$NUMBER_Ch_$CHAPTER.cpp" ]; then
echo "File Prob_$NUMBER_Ch_$CHAPTER.cpp already exists!"
else
echo "/* \n User: $U_NAME \n Problem: $NUMBER \n Output: \n */" >> "Prob_$NUMBER_Ch_$CHAPTER.cpp"
fi
done
See example 11.12 for c style for loop.
To create files use "Prob_"$NUMBER"Ch"$CHAPTER".cpp" at all the places.
Most shells allow a set -x at the top. This show you tracing of the script as it executes.
You need a trailing fi to close the if statement.
Shell math need NUMBER=$(expr $NUMBER + 1), it doesn't understand $NUMBER++.
You might find the printf command more handy than echo.
You will still have your variable use wrong in the loop and are only creating one file. I hope you can figure that out as this seems like homework.