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
Related
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 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 3 years ago.
Improve this question
The $_ variable, which should expand with the arguments of the last executed command in Bash, contains _lp_runtime_before. No matter how many times I run a command, that would be the content it has. Why?
Actually, $_ expand to the last argument of the last command line, according to the man page of bash:
[$_] expands to the last argument to the previous command, after expansion.
If you want the whole arguments, use !:*:
$ ls -a -l -h test
[blah blah]
$ last_command="!:*" > /dev/null
$ echo $last_command
-a -l -h test
I added a redirection of stdout to null device to prevent bash to print the expansion.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have a very long pattern file and medium-length text file. I simply want to know if the strings in the pattern file are present or not -- I don't care what line they're on. Is there a way to track which patterns are found and which not?
You can do something like this:
while read line; do
grep -q "$line" textFile
echo "${line}: $?"
done < patternFile
Loop over the patternFile and for every pattern invoke a grep -q on the textFile. grep -q will not produce any output, but it will set bash's exit status to 0 if the pattern was found and to 1 if it was not found.
As commented by that other guy, you can get a list with all matching patterns like this:
while read line; do
grep -q "$line" textFile && echo "$line"
done < patternFile
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 8 years ago.
Improve this question
I am trying to adapt the loop code from bash to csh:
while read file; do
if ! UPLOAD_FILE=$(ls "$UPLOAD_ARCHIVE_DIR"/*$file* 2>/dev/null); then
echo "could not find $file"
(( MISSING_COUNTER++ ))
continue
fi
ls -l "$UPLOAD_FILE" | sed 's/^[^ ]* *[^ ]* *[^ ]* *[^ ]* *[^ ]* *//'
cp "$UPLOAD_FILE" "$PROCESS_FILES_DIR"
DOS_FILE=$(basename "$UPLOAD_FILE")
SOR_FILE=$(echo $DOS_FILE | sed 's/.dat/.sor/')
unix2dos "$PROCESS_FILES_DIR"/"$DOS_FILE" 1>/dev/null 2>&1
mv "$PROCESS_FILES_DIR"/"$DOS_FILE" "$UPLOAD_PROCESS_DIR"
(( FOUND_COUNTER++ ))
done < "$1"
The input information comes from variable $input and contains a list, here is a sample record from the list: PL000000002002638908
So far, I have tried to use foreach and while loops without success, any help is greatly appreciate it!
You almost certainly don't need to translate your script from bash to csh.
/bin/sh is the Bourne shell, or something that works very much like it. This should be the case even on systems where csh is the default interactive shell and bash is unavailable.(On some systems, /bin/sh it may be a symlink to ksh, for example.)
bash is derived from the Bourne shell, and adds some bash-specific features.
You can confirm that /bin/sh is a Bourne-like shell by typing the following command at any shell prompt:
/bin/sh -c 'if true ; then echo Yes, this is a Bourne-like shell ; fi'
In the unlikely event that /bin/sh is really csh, the above will give you a syntax error.
It would be easier to modify your script to avoid bash-specific features than to translate it to csh. Read the bash manual, look for Bash-specific features, and modify your script to avoid them. (If that's even necessary; it may be that /bin/sh is something that supports at least some of them.)
Change the first line of your script to
#!/bin/sh
and see what error messages you get.
You might need to replace the
$(command)
syntax by the older
`command`
and this:
(( FOUND_COUNTER++ ))
to something using expr, perhaps:
FOUND_COUNTER=`expr $FOUND_COUNTER + 1`
The while read file ... loop should work as it is.
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