i have project in which i have to play a number of sound files at random, at the push of a button iam using an arduino yun. so far i can play the sounds from the sd card, however i want the random number to generate depending on the number of files in the sd card.i need help in reading the number of files through the command shell from the sketch
cd /mnt/sda1
ls | wc - l
when i this in the terminal i get the answer 4 and thats exactly the answer i need. i want to run this in the script, so far i have this however it doesnt seem to work
d.runShellCommand("ls | wc -l | cd /mnt/sda1");
result = d.parseInt();
Serial.println(result);
can anyone help me in fixing this
thank you
Your shell command has a few errors in it. Rather than pipe to a cd command, you can simply specify the directory when running ls. for example:
ls | wc -l | cd ~/Documents/
outputs nothing. However,
ls ~/Documents/ | wc -l
Outputs the number of files and folders in my documents folder.
So this command should work:
d.runShellCommand("ls /mnt/sda1| wc -l");
Related
By using bash script, I'm trying to detect whether a file has been created on a directory or not while running commands. Let me illustrate the problem;
#!/bin/bash
# give base directory to watch file changes
WATCH_DIR=./tmp
# get list of files on that directory
FILES_BEFORE= ls $WATCH_DIR
# actually a command is running here but lets assume I've created a new file there.
echo >$WATCH_DIR/filename
# and I'm getting new list of files.
FILES_AFTER= ls $WATCH_DIR
# detect changes and if any changes has been occurred exit the program.
After that I've just tried to compare these FILES_BEFORE and FILES_AFTER however couldn't accomplish that. I've tried;
comm -23 <($FILES_AFTER |sort) <($FILES_BEFORE|sort)
diff $FILES_AFTER $FILES_BEFORE > /dev/null 2>&1
cat $FILES_AFTER $FILES_BEFORE | sort | uniq -u
None of them gave me a result to understand there is a change or not. What I need is detecting the change and exiting the program if any. I am not really good at this bash script, searched a lot on the internet however couldn't find what I need. Any help will be appreciated. Thanks.
Thanks to informative comments, I've just realized that I've missed the basics of bash script but finally made that work. I'll leave my solution here as an answer for those who struggle like me.:
WATCH_DIR=./tmp
FILES_BEFORE=$(ls $WATCH_DIR)
echo >$WATCH_DIR/filename
FILES_AFTER=$(ls $WATCH_DIR)
if diff <(echo "$FILES_AFTER") <(echo "$FILES_BEFORE")
then
echo "No changes"
else
echo "Changes"
fi
It outputs "Changes" on the first run and "No Changes" for the other unless you delete the newly added documents.
I'm trying to interpret your script (which contains some errors) into an understanding of your requirements.
I think the simplest way is simply to rediect the ls command outputto named files then diff those files:
#!/bin/bash
# give base directory to watch file changes
WATCH_DIR=./tmp
# get list of files on that directory
ls $WATCH_DIR > /tmp/watch_dir.before
# actually a command is running here but lets assume I've created a new file there.
echo >$WATCH_DIR/filename
# and I'm getting new list of files.
ls $WATCH_DIR > /tmp/watch_dir.after
# detect changes and if any changes has been occurred exit the program.
diff -c /tmp/watch_dir.after /tmp/watch_dir.before
If the any files are modified by the 'commands', i.e. the files exists in the 'before' list, but might change, the above will not show that as a difference.
In this case you might be better off using a 'marker' file created to mark the instance the monitoring started, then use the find command to list any newer/modified files since the market file. Something like this:
#!/bin/bash
# give base directory to watch file changes
WATCH_DIR=./tmp
# get list of files on that directory
ls $WATCH_DIR > /tmp/watch_dir.before
# actually a command is running here but lets assume I've created a new file there.
echo >$WATCH_DIR/filename
# and I'm getting new list of files.
find $WATCH_DIR -type f -newer /tmp/watch_dir.before -exec ls -l {} \;
What this won't do is show any files that were deleted, so perhaps a hybrid list could be used.
Here is how I got it to work. It's also setup up so that you can have multiple watched directories with the same script with cron.
for example, if you wanted one to run every minute.
* * * * * /usr/local/bin/watchdir.sh /makepdf
and one every hour.
0 * * * * /user/local/bin/watchdir.sh /incoming
#!/bin/bash
WATCHDIR="$1"
NEWFILESNAME=.newfiles$(basename "$WATCHDIR")
if [ ! -f "$WATCHDIR"/.oldfiles ]
then
ls -A "$WATCHDIR" > "$WATCHDIR"/.oldfiles
fi
ls -A "$WATCHDIR" > $NEWFILESNAME
DIRDIFF=$(diff "$WATCHDIR"/.oldfiles $NEWFILESNAME | cut -f 2 -d "")
for file in $DIRDIFF
do
if [ -e "$WATCHDIR"/$file ];then
#do what you want to the file(s) here
echo $file
fi
done
rm $NEWFILESNAME
(edited)
Let say i have some directory structure like this:
lv1_directory
| file_contain_word_something.txt
| lv2_directory
so now i'm at lv2_directory and i have a code like this:
#!/bin/bash
findfile=$(ack -n 'something' . | wc -l)
cd ..
ls
echo $findfile
when i run the script it give me
lv2_directory file_contain_word_something.txt
0
but if i didn't assign it to variable it work like charm
#!/bin/bash
cd ..
ls
ack -n 'something' | wl -l
it give me
lv2_directory file_contain_word_something.txt
1
so i have to change it to this to work
#!/bin/bash
findfile=$(ack -n 'something' .. | wc -l)
cd ..
ls
echo $findfile
it give me the result i want
lv2_directory file_contain_word_something.txt
1
How can i use the first script and give me the result i want?
I think the problem here is:
You are currently inside lv2_directory which DOES NOT HAVE any file which matches the string 'something'. So when you fire ack from this dir itself, you get 0 for number of lines. Then you do cd...
#!/bin/bash
findfile=$(ack -n 'something' . | wc -l)
cd ..
ls
echo $findfile
Now, in your next snippet:
#!/bin/bash
cd ..
ls
ack -n 'something' | wl -l
You are first doing cd, so you are into lv1_directory, which has the file file_contain_word_something.txt. Then you fire your ack. Now it finds something in the txt file and hence, gives you 1 as the output(assuming there's only 1 matching line).
Like you wrote your script, it will never list (ls instruction), and count (wc instruction) in the same directory, so you have no result guarantee.
In addition, according to the directory in which you will launch the script, it may not work at all.
May you consider managing path at beginning of your script (and don't modify it between your instructions)?
Do you exactly know where is it on the system?
An alternative, may be to create an environment variable (for instance in your ~/.bash_profile file), and to use it at beginning of your script, ensuring it'll always be run in the good directory.
after some experiment i can achieve the result i want using function
#!/bin/bash
function findfile(){
ack -n 'something' | wc -l
}
cd ..
findfile
and its gonna give you 1
thank you for answering my question
Trying to access network drive (UNC) from the bash script. The network drive needs username and password.
i Can access UNC by running some individual commands like CD, net use .However unable to execute from a script.
follows below steps
1) Mount the drive to x drive by using below command from
Command : net use x: \\\\Server_name\\Directory /user:users pass /PERSISTENT:YES
Result :Sucess mounted x drive
2) test.sh
#!/bin/bash
ls /cygdrive/x
count_node1 = cat a.log b.log.1 v.log.2 |grep "&&&&" | sort -k1,2 | grep -c 'word'
#count_node1="got it"
echo helloworld
echo $count_node1
#end
Result: helloWorld
: No such file or directory/x
count_node1: command not found
3)Further, If I run each line from Cygwin individually it is working perfectly.
trying bash profile for first time really confused.
The order matter with net use:
net use x: \\\\Server_name\\Directory pass /user:users
See syntax of your shell (bash). Correct:
count_node1=$(cat a.log b.log.1 v.log.2 |grep "&&&&" | sort -k1,2 | grep -c 'word')
or
count_node1=$(grep '&&&&' a.log b.log.1 v.log.2 |sort -k1,2 | grep -c 'word')
Remove the carriage return characters from the ends of your script's lines, i. e. save it in unix instead of dos file format.
I'm trying to write a small shell script to find the most recently-added file in a directory and then move that file elsewhere. If I use:
ls -t ~/directory | head -1
and then store this in the variable VARIABLE_NAME, why can't I then then move this to ~/otherdirectory via:
mv ~/directory/$VARIABLE_NAME ~/otherdirectory
I've searched around here and Googled, but there doesn't seem to be any information on using variables in file paths? Is there a better way to do this?
Edit: Here's the portion of the script:
ls -t ~/downloads | head -1
read diags
mv ~/downloads/$diags ~/desktop/testfolder
You can do the following in your script:
diags=$(ls -t ~/downloads | head -1)
mv ~/downloads/"$diags" ~/desktop/testfolder
In this case, diags is assigned the value of ls -t ~/downloads | head -1, which can be called on by mv.
The following commands
ls -t ~/downloads | head -1
read diags
are probably not what you intend: the read command does not receive its input from the command before. Instead, it waits for input from stdin, which is why you believe the script to 'hang'. Maybe you wanted to do the following (at least this was my first erroneous attempt at providing a better solution):
ls -t ~/downloads | head -1 | read diags
However, this will (as mentioned by alvits) also not work, because each element of the pipe runs as a separate command: The variable diags therefore is not part of the parent shell, but of a subprocess.
The proper solution therefore is:
diags=$(ls -t ~/downloads | head -1)
There are, however, further possible problems, which would make the subsequent mv command fail:
The directory might be empty.
The file name might contain spaces, newlines etc.
This is a very noob question but I'm finding it difficult to nail it down quickly.
I want to write a bash script that lets me start and shut down tomcat as I require, regardless of my current working director.
I know how to write functions in bash, I want to know how to execute a .sh.
How do I do this?
Thanks
You want to use alias. Put this in your bashrc or profile for example:
alias lsft="find ./ -type f | grep -E '.*\.[a-zA-Z0-9]*$' | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq -c | sort -n"
So if you logout/login or run source .bash-profile you can run lsft and it will list all the files by type in the current directory