Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a file with contents like this
adv_dir=2
ami_pro=3
I have a variable $TEMP with value ami_pro, I want to increase the value of $TEMP by 1.
Want a bash script for this.
State of file after updates
adv_dir=2
ami_pro=4
Icky-ish, spooky indirection, but...
$: echo $TEMP
ami_pro
$: echo $ami_pro
4
$: (($TEMP++)) # $TEMP evals to ami_pro, which gets incremented
$: echo $TEMP
ami_pro
$: echo $ami_pro
5
$: let $TEMP++ # same, likely in any arithmetic context
$: echo $ami_pro
6
so...
TEMP=ami_pro # just setting in the env
grep "$TEMP=" file > $TEMP.tmp # grap the line we need to edit
. $TEMP.tmp # souce it to set the var
sed -i "s/$TEMP=${!TEMP}/$TEMP=$((++$TEMP))/" file # in-place edit
You could skip the tempfile with eval "$(grep "$TEMP=" file)" but eval makes me itch.
The sed is an in-place edit of file using double-quotes to allow the OS to pre-process the vars before making the update.
TEMP=ami_pro
so
$TEMP=${!TEMP}
is parsed by the OS into
ami_pro=$ami_pro
Since we sources the line that said ami_pro=3, that gets further parsed into
ami_pro=3
then
$TEMP=$((++$TEMP))
becomes ami_pro=$((++ami_pro)) which processes to
ami_pro=4
all sed gets is the result strings, so by the time sed starts parsing, what it sees is
s/ami_pro=3/ami_pro=4/
Once that edit is handled, we can break out of the loop.
You can use awk for that:
#!/bin/bash
TMP_FILE=$(mktemp)
awk -F= "/^${TEMP}=/ {print \$1 \"=\" \$2 + 1 \"*\"; next} 1" "${1}" > ${TMP_FILE} && mv ${TMP_FILE} "${1}"
rm ${TMP_FILE}
Pass the file with the data as a parameter to this script.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
When I run this code, the variable "thing" doesn't change its value to the command. I've tried everything and I just can't get it to work. I want thing to equal something like "1 history cd /bin
history cd /home/user/"
#!/bin/bash
val="thing"
function send () {
thing
thing=$(history | tail -n 2)
echo $thing
echo $val
# echo $last
if [ "$val" == *"this"* ]; then
echo "yes"
fi
exit 1
}
send
If you wonder why $(history | tail -n 2) returns nothing, it is because history lists commands previously ran in the current shell.
But your script is a new shell instance, so it does not carry the history of commands you ran before you execute your script.
If you want that, you have to source the script, not execute it. To source, do:
$ . thescript.bash
instead of
$ ./thescripts.bash
instead of this also
$ bash thescript.bash
Note: put your code in https://www.shellcheck.net/ to see syntax issues.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Please excuse me for my amateur language.
I have written a simple one line code to cat out content I want from a huge text file:
cat file | grep "value" | cut -f1 -d":"
It out put lines of paths of file from there on.
I want it to go on doing this:
cd into the paths one line at a time.
each time after cd run this command:
ls | grep .fileformat
Then let me run 3 commands I choose to, if I press [return] with no value it will ignore and listen for the next command. After three is done it will go on.
cd into the directory of the next line and repeating until the last line.
Sorry I couldn't figure this later part out as I didn't know where to start googling even.
Thank you for looking!
Edit 1: output of my initial command gives paths like this:
/home/user/path/to/file
So there is no ~, it should be able to cd into them no problem?
A slightly modified version of Allan Wind's answer that does what I THINK the OP wants (tried to reply as a comment to Allan but couldn't figure out code formatting properly):
sed -n '/value/s/\([^:]*\):.*/\1/p' file | while read d
do
echo -e "Entering $d"
cd $d
ls | grep .fileformat
for i in {1..3}; do
echo -e "Type your command #${i}:\n"
read -p '>' input < /dev/tty
[ -z "$input" ] && echo -e "\nDoing nothing this time...\n" && continue
eval "$input"
done
done
(Usual caveats of reading interactively + using eval being dangerous)
Here is the skeleton of an answer to help you ask a better question:
sed -n '/value/s/\([^:]*\):.*/\1/p' file | while read d
do
(
cd d
ls | grep .fileformat
read -p "3 commands? " c
[ -z "$c" ] && continue
cd d
eval "$c"
)
done
(Usual caveats of reading interactively + using eval being dangerous)
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm modifying this recursive directory crawling script from https://unix.stackexchange.com/questions/494143/recursive-shell-script-to-list-files
my plan is just to concatenate strings of the output of text files in my directory
so like: content+= content + cat file.txt, I feel like what I have isn't too far off but right now the output is blank and I guess I'm misunderstanding how to separate the cat function from the string concat portion
I tried using less instead of cat but that produces the same result I'm following the link below but none of the examples seem to produce an output for me
How to concatenate string variables in Bash
#! /bin/bash
echo "starting script"
content="start =>"
walk_dir () {
shopt -s nullglob dotglob
for pathname in "$1"/*; do
if [ -d "$pathname" ]; then
walk_dir "$pathname"
else
case "$pathname" in
*.txt|*.doc)
#printf '%s\n' "$pathname"
content+=(cat "$pathname") #add file contents to the previous string
esac
fi
done
echo "$content"
}
DIR=/c/Users/xxxx/Desktop/xxxx
walk_dir "$DIR"
pretty new to bash scripting but
Had a quick look - I think you are missing the $ sign in concat.
content+=$(cat "$pathname")
Alternatively, you can use backquote instead of parentheses without $.
You will need to say content+="$(cat "$pathname")" to append the
output of cat to the scalar variable content.
Or you can just say:
shopt -s extglob globstar
content="$(cat **/*#(.txt|.doc))"
echo "$content"
to concatenate the contents of the text/document files recursively.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I a trying to read a file line by line and add the value of each line after making some changes to a variable.
Currently I am using this-
COM="Something i"
while IFS= read -r line || [ -n "$line" ];
do
LINE="Line${line/=/,}End"
COM="$COM$LINE"
done < Vars
COM="$COM done"
echo "Vars" | piping_into_some_other_application
The content of file vars-
VAL=something
VAL2=somethingelse
VAL3=some
VAL4=vals
I finally expect COM to be-
Something iLineVAL,somethingEndLineVAL2,somethingelseEndLineVAL3,someEndLineVAL4,valsEnd done
But I get-
LineVAL4,valsEnd done
With Your solution $LINE and $COM gets overwritten with every iteration instead of appending.
You can do this with gawk if that is available too look this:
awk '{gsub("=",",") ; V = V "Line" $1 "End" } END { print "Something i" V "done"}' INPUTFILE | some_other_application
(And You can do it with sed, perl etc.)
With bash it can be done like
COM=""
while IFS= read -r line ; do
COM="${COM}Line${line/=/,}end"
done < INPUTFILE
echo "Something i${COM} done" | some_other_program
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I have a date in file called lastbackup with date in the yyyymmdd format. Now, I would like to compare this string with current date in the same format in BASH.
I have:
#!/bin/bash
cd ~
DATE=`date +%Y%m%d`
LASTBACKUP=sudo cat ./lastbackup
echo $LASTBACKUP
echo $DATE
if [ "$LASTBACKUP" == "$DATE" ]; then
echo "Do nothing, already processed."
else
echo "Do something, not processed"
echo -n $DATE > ./lastbackup
fi
I keep getting Do something... and I can't figure out why DATE and LASTBACKUP variables are different, because in output it looks like they are equal:
$ testeq
20140407
20140407
Do something, not processed
When I use (as suggested by Alex):
echo "LASTBACKUP: '$LASTBACKUP'"
echo "DATE: '$DATE'"
Then I get:
$ testeq
20140407LASTBACKUP: ''
DATE: '20140407'
And now it is clear to me what is going on.
Here's the reason this is wrong:
LASTBACKUP=sudo cat ./lastbackup
When you execute a command in this form:
var=val var2=val2 ... command arg arg ...
The variables are put into the environment of the command, and only into that environment. So, while cat is running, it has an environment variable named LASTBACKUP with the value "sudo". Once cat is finished, that variable will disappear.
The contents of the ./lastbackup file get cat'ed to stdout. I'm surprised you don't see a blank line when you echo $LASTBACKUP. Check your files for CRLF line endings, or perhaps the ./lastbackup file does not end with a newline.
When you're debugging and printing variables out, do something more obvious to see their value:
printf "LASTBACKUP='%s'\n" "$LASTBACKUP"
# or
for var in DATE LASTBACKUP; do
printf "%s='%s'\n" "$var" "${!var}"
done
bash has a builtin way to read a file so you don't have to call cat: this will have you a couple of milliseconds:
lastbackup=$(< ./lastbackup)
Get out of the habit of using ALL_CAPS_VARS -- one day you'll use PATH=something and then wonder why your script stops working.
Yep, the problem is probably that you're not actually initializing the LASTBACKUP variable anywhere.
But the fact that you're trying to read it with sudo bothers me. Doesn't the user that runs the script has permission to read a file that is in its $HOME? You are cd'ing into ~, which is the user's home, but since you're sudoing its read makes me think that maybe that file is in /root/lastbackup? Why would you sudo its reading otherwise?
This should do the trick:
#!/bin/bash
# For testings:
# date +%Y%m%d > $HOME/lastbackup # Uncomment to create a "./lastbackup" test file.
# Let's beging
cd ~
DATE=`date +%Y%m%d`
LASTBACKUP=`cat ./lastbackup`
echo $LASTBACKUP
echo $DATE
if [ "$LASTBACKUP" == "$DATE" ]; then
echo "Do nothing, already processed."
else
echo "Do something, not processed"
echo -n $DATE > ./lastbackup
fi
Another option, if you're running a fairly new version of bash, and since your date format doesn't have any non-number character as separator (no - , / ...) would be consider the values numbers in the if:
if (( $LASTBACKUP == $DATE )); then
echo "Do nothing, already processed."
else
echo "Do something, not processed"
echo -n $DATE > ./lastbackup
fi
And, while testing, don't escape the LASTBACKUP or DATE variables with quotation marks ". If there was a problem reading the file (or getting the current date, but I doubt that one) you'll see an error. It'll help debugging.