I'm trying to make a bash script that goes in the .gitmodules file, gets the path and branch of each submodule then goes where the submodule is located and git checkout to the right branch. BUT the git commands doesn't work well when I run the script but work well when I enter them manully in the terminal.
Keep getting stuff like :
-> fatal not a git repository (or any of the parent directories): .git
(I then added git init in the while loop)
-> fatal : you are on a branch yet to be born
Can you tell me what i'm missing here plz ?
#!/bin/bash
sed -n '/path/p' .gitmodules > tampon01.txt #selectionne uniquement les ligne contenant path
sed -n '/branch/p' .gitmodules > tampon02.txt #selectionne uniquement les ligne contenant path
cut -d = -f 2- tampon01.txt > pathlist.txt #selectionne uniquement les champs de caractères après le "=") pour les path
cut -d = -f 2- tampon02.txt > branchlist.txt #selectionne uniquement les champs de caractères après le "=") pour les branch
let "i=1"
Pnb_lignes=$(sed -n '$=' pathlist.txt)
Bnb_lignes=$(sed -n '$=' branchlist.txt)
echo $Pnb_lignes "path trouvées"
echo $Bnb_lignes "branch trouvées"
#while [ $i < $nb_lignes ]
#if [$Pnb_lignes -le $Bnb_lignes] #test pour trouver le minimum entre le nb de lignes trouvée dans chaque fichier
if [ 5 -le 2 ] #test pour trouver le minimum entre le nb de lignes trouvée dans chaque fichier
then
let "nb_lignes = Pnb_lignes"
else
let "nb_lignes = Bnb_lignes"
fi
echo $nb_lignes "actions a realiser"
while (($i < $nb_lignes))
do
#pa= $(sed -n "$i"p tampon02.txt) #retourne la ligne i
pa= sed -n "$i"p pathlist.txt
br= sed -n "$i"p branchlist.txt
#echo $pa "xxxx"
cd $pa
git init
git checkout $br
cd /mnt/c/_D/Devel/taoSet
echo ".............................."
let "i = $i +2"
done
echo $i "actions realisees"
#rm -v tampon01.txt tampon02.txt branchlist.txt pathlist.txt
In bash, there cannot be any spaces around the = sign in an assignment statement.
In a terminal, it may be re-using the values from previously assigned variables.
While in a bash script, since old / global variables are not accessible by default, it may assign null values or fail for incorrectly written commands and proceed ahead.
This is a plausible reason that you get different behaviours in both approaches.
The command substitution seems to be missing, leading to the $pa and $br variables to be undefined in these lines:
pa= sed -n "$i"p pathlist.txt
br= sed -n "$i"p branchlist.txt
It should be
pa=$(sed -n "$i"p pathlist.txt)
br=$(sed -n "$i"p branchlist.txt)
Other things could be broken as well, haven't checked thoroughly.
Related
This question already has answers here:
bash file returns unexpected token `$'do\r''
(7 answers)
Closed 3 years ago.
I'm developing an opensource program , I need to find out the error here.
This is a linux-meant BASH script.
I can't figure out what's wrong with this code:
#!/usr/bin/env bash
declare -a dependenciesList=(
"element2"
"element3"
"element4"
)
#check des dependences dans le systeme actuel:
#____________procedure de verification de l'existance de la dependance
exists ()
{
command -v "$1" >/dev/null 2>&1
}
#____________procedure de l'installation de la dependance
install ()
{
echo "[INSTALL] '$1' installation started"
apt-get install "$1"
}
#____________procedure coeur
for i in "${dependenciesList[#]}"
do
echo "[CHECK] Verification de l'existance de la dependence : $i"
# or do whatever with individual element of the array
if exists "$i"; then
echo " $i [OK]"
else
echo "[CHECK][ERROR][CRITICAL] Le systeme n'a pas $i ,appel a la procedure d'installation "
install "$i"
fi
done
The code blocks at the function exits always , and returns this error log:
./linux.dependencies.check.bash: syntax error near unexpected token `$'\r''
'/linux.dependencies.check.bash: `exists ()
You saved your script with Windows line endings (\r\n instead of just \n), which is confusing the Linux program bash. Run dos2unix on the script to fix it.
I'm currently writing a little script in bash to ask the user for some setting. The script is asking some infos, and then run other scripts. I have to run it under sudo, because I have some apt-get install in scripts.
But when I launch it with sudo, I have this error :
./install_all: 1: ./install_all: Syntax error: "(" unexpected
Here is the beginning of my script :
function askAllInfo() {
echo -e "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
| Choix de la version de PHP |
| |
| 1.) PHP5 |
| 2.) PHP7 |
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#\n"
read -e -p "Selectionner la version PHP pour l'installation de Maarch (PHP5) : " phpVERSION
if [ "$phpVERSION" == "1" ] || [ "$phpVERSION" == "" ]; then
phpVersion='5'
elif [ "$phpVERSION" == "2" ]; then
phpVersion='7'
fi
echo -e "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
| Choix du chemin d'installation de MAARCH : |
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#\n"
read -e -p "Merci de spécifier le chemin pour l'installation de Maarch (/var/www/maarch_courrier) : " maarchURL
if [ "$maarchURL" == "" ]; then
MAARCH_SITE=/var/www/maarch_courrier
else
MAARCH_SITE=$maarchURL
fi
echo -e "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
| Choix du chemin des docservers : |
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#\n"
read -e -p "Merci de spécifier le chemin des docservers (/var/docserver) : " docserversURL
if [ "$docserversURL" == "" ]; then
DOCSERVER_PATH=/var/docserver
else
DOCSERVER_PATH=$docserversURL
fi
echo -e "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
| Choix du nom de la BDD : |
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#\n"
read -e -p "Merci de spécifier le nom de la base de donnée (maarch) : " databaseName
if [ "$databaseName" == "" ]; then
DATABASE_NAME=maarch
else
DATABASE_NAME=$databaseName
fi
echo -e "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
| Choix du login de l'utilisateur de la BDD : |
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#\n"
read -e -p "Merci de spécifier le login de l'utilisateur de la base de donnée (postgres) : " databaseUser
if [ "$databaseUser" == "" ]; then
DATABASE_USER=postgres
else
DATABASE_USER=$databaseUser
fi
echo -e "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
| Choix du mdp de l'utilisateur de la BDD : |
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#\n"
read -e -p "Merci de spécifier le mot de passe de l'utilisateur de la base de donnée (postgres) : " databasePass
if [ "$databasePass" == "" ]; then
DATABASE_PASSWORD=postgres
else
DATABASE_USER=$databasePass
fi
}
askAllInfo
How can I fix this issue ?
Thanks in advance
Assuming you're showing the very beginning of the script, I think it's probably running under regular sh. The sh language does not support the function keyword (reference). If you add
#!/bin/bash
as the first line of your script, so that it runs under bash, you should be OK.
Alternatively, you can remove the word function from the first line of your script. However, it's better to add the #! so you can make use of the bash features.
As a test, I tried using dash (which doesn't support some of the bash extensions) on Cygwin. The line
function foo() {
gave me the corresponding error:
dash: 1: Syntax error: "(" unexpected
but
foo() {
worked fine.
I just started shell scripting and for test purposes I'm trying to create scripts for my personal use.
I have a home fileserver that I sync from and to sometimes and I'm trying to create an interactive script so i can make the task of mp3 syncing easier.
Here is my script :
#!/bin/bash
##############################################
############ MP3 SYNC SCRIPT ##############
##############################################
#### REV: 01 20/07/2015
#### Author: Marcio Ribeiro
echo -e "Sincronizar do storage para o note ( escolha 01 ) ou do note para storage ( escolha 02 ): \n 01 Destino final Note: \n 02 Destino final Storage:"
read DESTINO
DESTINO_CK=[0]-[12]
while [ $DESTINO != $DESTINO_CK ] ; do
read -p "Por favor escolha entre 01 ou 02:" DESTINO
done
echo -e "Digite a letra inicial da banda que deseja utilizar na sincronização em CAPS"
read LETRA
LETRACK={AZ}
while [ "$LETRA" != $LETRACK ]; do
read -p "Digite a letra inicial da banda que deseja utilizar na sincronização em CAP:" LETRA
done
LEFT="/storage/Marcio/Mp3/${LETRA}/"
RIGHT="/data/mp3/${LETRA}/"
if [ $DESTINO = "01" ]; then
echo -e "`rsync -rvz ${LEFT} ${RIGHT}`; \n `ls -lha ${RIGHT}`"
else
echo -e "`rsync -rvz ${RIGHT} ${LEFT}`; \n `ls -lha ${LEFT}`"
fi
I got the basics working now I'm trying to limit the user interaction to what I really want but I'm failing.
Basically on the first user prompt I only want to accept 01 or 02 as input and on the second user prompt only a capital single letter.
Anyone have a clue why I'm failing on something so simple?
I got it working, it's not a pretty code or the best logic but it works :
!/bin/bash
##############################################
############ MP3 SYNC SCRIPT ##############
##############################################
#### REV: 01 20/07/2015
#### Author: Marcio Ribeiro
echo -e "Sincronizar do storage para o note ( escolha 1 ) ou do note para storage ( escolha 2 ): \n 1: Destino final Note \n 2: Destino final Storage"
read DESTINO
until [ "$DESTINO" = "1" ] || [ "$DESTINO" = "2" ];
do
read -p "Por favor escolha entre 1 ou 2:" DESTINO
done
####
echo -e "Digite a letra inicial da banda que deseja utilizar na sincronização em CAPS"
read LETRA
LETRA_CK='[A-Z]'
while [[ "$LETRA" != $LETRA_CK ]];
do
read -p "Digite a letra inicial da banda que deseja utilizar na sincronização em CAPS:" LETRA
done
####
LEFT="/storage/Marcio/Mp3/${LETRA}/"
RIGHT="/data/mp3/${LETRA}/"
if [ $DESTINO = "01" ]; then
echo -e "`rsync -rvz ${LEFT} ${RIGHT}`; \n `ls -lha ${RIGHT}`"
else
echo -e "`rsync -rvz ${RIGHT} ${LEFT}`; \n `ls -lha ${LEFT}`"
fi
Any ideas for improvement are welcome.
I have to make a phone_book in shell (bash)..
Here's what the program should do.
Add a number : You ask for the name and the number.If it doesn't exist already ( verification) then add a file in the same directory called $name and contain 1 line: the number.
Obtain the liste of names already saved.
Look for a number by giving his name ( we have to verify also if it exists or not.
modify a number ( verification also)
looking for a name by giving his number.( verification).
I Think that we have to use case I looked in the net, but I have difficulties with Shell.
Hope you helps me guys. Don't hesitate to ask me questions. Thanks
#!/bin/bash
echo " 1)Ajouter une fiche
2)Obtenir la liste des noms déjà enregistrés
3)Chercher un numéro de téléphone
4)Modifier un numero de téléphone
5)Rechercher un nom"
read x
case $x in
1)
echo " Tapez le nom à rajouter"
read nom
touch $nom
;;
UPDATE:
I have almost finished it, I have a problem with the 5) when i type an existant number , it always telling me that it doesn't exist..
Feel free to make some improvement in my code :)
#!/bin/bash
echo " 1)Ajouter une fiche
2)Obtenir la liste des noms déjà enregistrés
3)Chercher un numéro de téléphone
4)Modifier un numero de téléphone
5)Rechercher un nom"
read x
case $x in
1)
echo " Tapez le nom à rajouter"
read nom
while [ -f $nom ]; do
echo "Le fichier existe déjà"
echo " Tapez le nom à rajouter"
read nom
done
touch $nom
echo " Maintenant, tapez le numero de la personne à rajouter"
read numero
echo $numero >> $nom
;;
2)
echo $(ls);;
3)
echo " Tapez le nom de la personne que vous recherchez"
read nomrech
while [ ! -f $nomrech ]; do
echo "Le fichier n'existe pas"
read nomrech
done
cat $nomrech
;;
4)
echo "Tapez le nom d'un contacte à modifier"
read nommodif
while [ ! -f $nommodif ]; do
echo "Le fichier n'existe pas"
read nommodif
done
echo "Tapez le nouveau numéro à modifier"
read nouvnum
echo $nouvnum > $nommodif
;;
5)
echo " Tapez le numero de la personne que vous cherchez"
read numchercher
while ! grep -i "$numchercher" * ; do
echo "ce numero n'existe pas "
read nomchercher
done
grep $numchercher *
;;
esac
First of all, you need to think about how you will actually store the datas. Then, try to associate an action to each items:
Create a file named by the input containing one single line
browse the folder and extract all the filenames in that directory
find a file in a directory, given its name
modify the content of a file given its name (you can trash the content of the file at that point)
Find a filename given a pattern
So basically, I think you can manage to do the assignment with the following commands: cat, find, *, grep and that's it!
Update:
For your last question (5th point), it seems to me that your code is really complicated. Have a look on this sample:
$ echo 0123456789 > john
$ echo 0987654321 > bob
$ grep 0987654321 *
bob:0987654321
$ grep jfkljlfds *
$ echo $?
1
$ grep 0123456789 *
john:0123456789
$ echo $?
0
$ false
$ echo $?
1
$ false || echo "oops that one didn't work"
oops that one didn't work
Now I think you have everything you need to keep going.
$? is the return code from previous command. If you have a look on man grep (1):
EXIT STATUS
The exit status is 0 if selected lines are found, and 1 if not found. If an error occurred the exit status is 2. (Note: POSIX error handling
code should check for '2' or greater.)
So basically, the trick using the or operator (||) is used to display an error only if the left part returned false.
I suppose read name; grep $name * || echo "$name was not found" would do the trick.
And by the way, you're often asking arguments twice (after checking). You shouldn't need that. The variable still exists after your test.
I'll explain my goal first to avoid "XY Problem" misunderstandings.
I want to be able to produce a file (on Linux) that, when downloaded to a Windows machine and double clicked, will open a (ms office, but it shouldn't matter IIUC) file with a known path (on the local windows machine) preset by the server.
It seems what I'm trying to do is possible if I include the path of the file I want to open (and neither of the other details regarding the volume it's stored in etc) in the lnk file.
I first checked the lnk file format specs trying to generate the file in a python script but that's not my piece of cake (I never wrote code to handle binary files before). Besides, there are many features of that format that I want to ditch, but I still have to grok their flags/fields/lenghts/termination etc.
Then I stumbled upon the winedump utility and some .lnk files created by WINE in my ~/.wine folder.
There must be some function in the WINE codebase that is able to generate a lnk file, but I couldn't find it.
Where is it?
Is it in the form of a command like win's mklink?
If not (and I guess it's a function somewhere if it's not) can you point it to me so that I can write a wrapper command?
Or is there any library that can write lnk files and run on GNU/Linux?
These are untested by me but I did find 2 tools on this site which does describe the 2 tools as follows:
This application allow you to create Windows Shortcut files (extension .LNK) without needing a Windows OS.
The first app is a C app, the second is a Bash shell script. Here's the Shell script, mslink.sh:
#!/bin/bash
#############################################################################################
# mslink.sh v1.0
#############################################################################################
# Ce script permet de créer un Raccourci Windows (Fichier .LNK)
# Script créé en se basant sur la doc
# http://msdn.microsoft.com/en-us/library/dd871305.aspx
#############################################################################################
OPTIONS=$(getopt -q -n ${0} -o hl:o:p -l help,lnk-target:,output-file:,printer-link -- "$#")
eval set -- ${OPTIONS}
IS_PRINTER_LNK=0
while true; do
case "$1" in
-h|--help) HELP=1 ;;
-l|--lnk-target) LNK_TARGET="$2" ; shift ;;
-o|--output-file) OUTPUT_FILE="$2" ; shift ;;
-p|--printer-link) IS_PRINTER_LNK=1 ;;
--) shift ; break ;;
*) echo "Option inconnue : $1" ; exit 1 ;;
esac
shift
done
if [ $# -ne 0 ]; then
echo "Option(s) inconnue(s) : $#"
exit 1
fi
[ ${#LNK_TARGET} -eq 0 ] || [ ${#OUTPUT_FILE} -eq 0 ] && echo "
Usage :
${0} -l cible_du_fichier_lnk -o mon_fichier.lnk [-p]
Options :
-l, --lnk-target Précise la cible du raccourci
-o, --output-file Enregistre le raccourci dans un fichier
-p, --printer-link Génère un raccourci de type imprimante réseau
" && exit 1
#############################################################################################
# Fonctions
#############################################################################################
function ascii2hex() {
echo $(echo -n ${1} | hexdump -v -e '/1 " x%02x"'|sed s/\ /\\\\/g)
}
function gen_IDLIST() {
ITEM_SIZE=$(printf '%04x' $((${#1}/4+2)))
echo '\x'${ITEM_SIZE:2:2}'\x'${ITEM_SIZE:0:2}${1}
}
function convert_CLSID_to_DATA() {
echo -n ${1:6:2}${1:4:2}${1:2:2}${1:0:2}${1:11:2}${1:9:2}${1:16:2}${1:14:2}${1:19:4}${1:24:12}|sed s/"\([A-Fa-f0-9][A-Fa-f0-9]\)"/\\\\x\\1/g
}
#############################################################################################
# Variables issues de la documentation officielle de Microsoft
#############################################################################################
HeaderSize='\x4c\x00\x00\x00' # HeaderSize
LinkCLSID=$(convert_CLSID_to_DATA "00021401-0000-0000-c000-000000000046") # LinkCLSID
LinkFlags='\x01\x01\x00\x00' # HasLinkTargetIDList ForceNoLinkInfo
FileAttributes_Directory='\x10\x00\x00\x00' # FILE_ATTRIBUTE_DIRECTORY
FileAttributes_File='\x20\x00\x00\x00' # FILE_ATTRIBUTE_ARCHIVE
CreationTime='\x00\x00\x00\x00\x00\x00\x00\x00'
AccessTime='\x00\x00\x00\x00\x00\x00\x00\x00'
WriteTime='\x00\x00\x00\x00\x00\x00\x00\x00'
FileSize='\x00\x00\x00\x00'
IconIndex='\x00\x00\x00\x00'
ShowCommand='\x01\x00\x00\x00' # SW_SHOWNORMAL
Hotkey='\x00\x00' # No Hotkey
Reserved='\x00\x00' # Valeur non modifiable
Reserved2='\x00\x00\x00\x00' # Valeur non modifiable
Reserved3='\x00\x00\x00\x00' # Valeur non modifiable
TerminalID='\x00\x00' # Valeur non modifiable
CLSID_Computer="20d04fe0-3aea-1069-a2d8-08002b30309d" # Poste de travail
CLSID_Network="208d2c60-3aea-1069-a2d7-08002b30309d" # Favoris réseau
#############################################################################################
# Constantes trouvées à partir de l'analyse de fichiers lnk
#############################################################################################
PREFIX_LOCAL_ROOT='\x2f' # Disque local
PREFIX_FOLDER='\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # Dossier de fichiers
PREFIX_FILE='\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # Fichier
PREFIX_NETWORK_ROOT='\xc3\x01\x81' # Racine de serveur de fichiers réseau
PREFIX_NETWORK_PRINTER='\xc3\x02\xc1' # Imprimante réseau
END_OF_STRING='\x00'
#############################################################################################
# On retire l'anti-slash final s'il y en a un
LNK_TARGET=${LNK_TARGET%\\}
# On sépare le chemin racine du lien de la cible finale
# On distingue aussi si le lien est de type local ou réseau
# On définie la valeur Item_Data suivant le cas d'un lien réseau ou local
IS_ROOT_LNK=0
IS_NETWORK_LNK=0
if [[ ${LNK_TARGET} == \\\\* ]]; then
IS_NETWORK_LNK=1
PREFIX_ROOT=${PREFIX_NETWORK_ROOT}
Item_Data='\x1f\x58'$(convert_CLSID_to_DATA ${CLSID_Network})
TARGET_ROOT=${LNK_TARGET%\\*}
if [[ ${LNK_TARGET} == \\\\*\\* ]]; then
TARGET_LEAF=${LNK_TARGET##*\\}
fi
if [ ${TARGET_ROOT} == \\ ]; then
TARGET_ROOT=${LNK_TARGET}
fi
else
PREFIX_ROOT=${PREFIX_LOCAL_ROOT}
Item_Data='\x1f\x50'$(convert_CLSID_to_DATA ${CLSID_Computer})
TARGET_ROOT=${LNK_TARGET%%\\*}
if [[ ${LNK_TARGET} == *\\* ]]; then
TARGET_LEAF=${LNK_TARGET#*\\}
fi
[[ ! ${TARGET_ROOT} == *\\ ]] && TARGET_ROOT=${TARGET_ROOT}'\'
fi
if [ ${IS_PRINTER_LNK} -eq 1 ]; then
PREFIX_ROOT=${PREFIX_NETWORK_PRINTER}
TARGET_ROOT=${LNK_TARGET}
IS_ROOT_LNK=1
fi
[ ${#TARGET_LEAF} -eq 0 ] && IS_ROOT_LNK=1
#############################################################################################
# On sélectionne le préfixe qui sera utilisé pour afficher l'icône du raccourci
if [[ ${TARGET_LEAF} == *.??? ]]; then
PREFIX_OF_TARGET=${PREFIX_FILE}
TYPE_TARGET="fichier"
FileAttributes=${FileAttributes_File}
else
PREFIX_OF_TARGET=${PREFIX_FOLDER}
TYPE_TARGET="dossier"
FileAttributes=${FileAttributes_Directory}
fi
# On convertit les valeurs des cibles en binaire
TARGET_ROOT=$(ascii2hex ${TARGET_ROOT})
TARGET_ROOT=${TARGET_ROOT}$(for i in `seq 1 21`;do echo -n '\x00';done) # Nécessaire à partir de Vista et supérieur sinon le lien est considéré comme vide (je n'ai trouvé nul part d'informations à ce sujet)
TARGET_LEAF=$(ascii2hex ${TARGET_LEAF})
# On crée l'IDLIST qui représente le cœur du fichier LNK
if [ ${IS_ROOT_LNK} -eq 1 ];then
IDLIST_ITEMS=$(gen_IDLIST ${Item_Data})$(gen_IDLIST ${PREFIX_ROOT}${TARGET_ROOT}${END_OF_STRING})
else
IDLIST_ITEMS=$(gen_IDLIST ${Item_Data})$(gen_IDLIST ${PREFIX_ROOT}${TARGET_ROOT}${END_OF_STRING})$(gen_IDLIST ${PREFIX_OF_TARGET}${TARGET_LEAF}${END_OF_STRING})
fi
IDLIST=$(gen_IDLIST ${IDLIST_ITEMS})
#############################################################################################
if [ ${IS_NETWORK_LNK} -eq 1 ]; then
TYPE_LNK="réseau"
if [ ${IS_PRINTER_LNK} -eq 1 ]; then
TYPE_TARGET="imprimante"
fi
else
TYPE_LNK="local"
fi
echo "Création d'un raccourci de type \""${TYPE_TARGET}" "${TYPE_LNK}"\" avec pour cible "${LNK_TARGET} 1>&2
echo -ne ${HeaderSize}${LinkCLSID}${LinkFlags}${FileAttributes}${CreationTime}${AccessTime}${WriteTime}${FileSize}${IconIndex}${ShowCommand}${Hotkey}${Reserved}${Reserved2}${Reserved3}${IDLIST}${TerminalID} > "${OUTPUT_FILE}"