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.
Related
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.
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 4 years ago.
Improve this question
I'm new to Bash and trying to modify a file using sed. Consider this simple example:
#!/bin/bash
shopt -s extglob
file="/root/test.txt"
# Modify the file.
sed "s/apple/orange/g" $file -> $file.tmp && mv $file.tmp $file
I run the script, and it hangs. Looking at the directory:
ls
test.sh test.txt test.txt.tmp
Shows test.txt.tmp is created, but mv is not working.
What is wrong with the script?
The problem is in the following line:
sed "s/apple/orange/g" $file -> $file.tmp && mv $file.tmp $file
Bash interprets this line as:
sed "s/apple/orange/g" $file - > $file.tmp && mv $file.tmp $file
Notice the subtle difference (the space between - and >).
Now, what is happening? The - <hyphen> is interpreted to be a file. More specifically /dev/stdin. This implies that sed is awaiting input from /dev/stdin. That is also the reason why it is hanging. It is actually not hanging but awaiting input. The file $file.tmp is created, but since the sed command is still executing, the mv is not happening.
The standard input shall be used if no file operands are specified, and shall be used if a file operand is - and the implementation treats the - as meaning standard input. Otherwise, the standard input shall not be used. See the INPUT FILES section.
source: POSIX sed standard
Also related: Usage of a dash in place of a filename
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
#!/bin/sh
num=1
cat $1 | while read LINE
do
num=`expr $num + 1`
done
echo $num
Your script is spawning a sub-shell when you use pipe after useless cat. All the changes to $num made inside sub-shell get lost after while loop ends and you get back to parent shell.
You should initialize num with 0 not 1
It is better to not to use all capital letter variable names to avoid collision with internal shell variables.
Instead of reverse tick you should use $(...) for command substitution.
You should use:
#!/bin/sh
num=0
while read -r line
do
num=$(expr $num + 1)
done < "$1"
echo $num
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.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Can anyone explain the part where read i is used. Where did the i come from.
scp -i ~/.ssh/id_rsa.sample gaara#stuid.student.com:ready/$2/*.zip ./$2 > slate.out 2>&1
ls -1 $2/* > curr.lst 2>/dev/null
while
read i
do
if
test -e ../done/"$i"
then
diff "$i" ../done/"$i" >/dev/null 2>&1
if
test $? -eq 0
then
rm "$i"
fi
fi
done < curr.lst
This syntax for read is commonly used to process multiple lines from a file. Let's simplify things by omitting the inner loop:
while
read i
do
# Process i
done < curr.lst
The 'while x do; done' syntax is pretty basic and easily understood, but the addition of the I/O redirect can be confusing. When you add the < curr.lst after done, it means "use the contents of this file as stdin for the conditional. So, if you now omit the loop, you get:
read i < curr.lst
It is now clear that read is getting its input from curr.lst and setting the variable i to the contents of each line. So, what that block of code basically means is "process each line of curr.lst as the variable i with the code inside the loop.
"read" , according to man page (type man page in a shell), read from a file descriptor.
In your code, the loop is made for each row from "curr.lst", which are put in the variable $i