Related
I am attempting to create a script that can install (automate) veracrypt on a CentOS7 system.
The downloaded veracrypt file comes as a .bz2 file (veracrypt-1.23-setup.tar.bz2). After unzipping the bzip filebzip2 -dk veracrypt-1.23-setup.tar.bz2, I then unzip the resulting .tar file tar -xf /home/$USER/veracrypt-1.23-setup.tar. At this point I can (if I) manually call the veracrypt script ./veracrypt-1.23-setup-gui-x64 from the bash terminal I am presented the following veracrypt installer prompt.
The veracrypt installer prompt is looking for the user to press either number 1 or 2 on the keyboard and then Enter (which I manually typed into the prompt window shown below for visualization purposes), before pressing enter again to proceed to the license agreement.
I am looking for a bash command that will simply choose (or type) number 2 and then input on my behalf so that I don't need to interact with the prompt at all.
I have tried the following commands in my script to no avail:
#!/bin/bash
cp ./veracrypt-1.23-setup.tar.bz2 /home/$USER
cd /home/$USER
bzip2 -dk veracrypt-1.23-setup.tar.bz2
tar -xf /home/$USER/veracrypt-1.23-setup.tar
echo -n '2' | ./veracrypt-1.23-setup-gui-x64
And
#!/bin/bash
cp ./veracrypt-1.23-setup.tar.bz2 /home/$USER
cd /home/$USER
bzip2 -dk veracrypt-1.23-setup.tar.bz2
tar -xf /home/$USER/veracrypt-1.23-setup.tar
./veracrypt-1.23-setup-gui-x64 2
If I can find the command to pass the input into the script I'm pretty sure I can alter that command to proceed through the rest of the license agreement.
Thanks in advance for the supprot.
You can use a Here Document, see man bash under the Here Documents section. This will allow you to redirect input to the veracrypt installer as if it was coming from stdin. You can add to your script:
./veracrypt-1.23-setup-gui-x64 << EOF
2
EOF
And that should take care of you. Let me know if you have any problems or further questions. (you can change the heredoc sigil from EOF to anything you like as long as it is consistent) Additionally do not indent the heredoc without seeing the man page for use of the hyphen (though I wouln't recommend doing so as you must use the tab character as spaces won't do.
Another option is just to pipe 2 to the installer, e.g.
echo "2" | ./veracrypt-1.23-setup-gui-x64
(don't include -n)
Both accomplish the same thing. The key is 2 must be available to the installer on stdin, not as an argument.
I want to watch a folder on my Mac and then execute a bash script, passing it the name of whatever file/folder was just moved into or created in the watched directory.
fswatch
fswatch is a small program using the Mac OS X FSEvents API to monitor a directory.
When an event about any change to that directory is received, the specified
shell command is executed by /bin/bash
If you're on GNU/Linux,
inotifywatch (part of the
inotify-tools package on most distributions) provides similar
functionality.
Update: fswatch can now be used across many platforms including BSD, Debian, and Windows.
Syntax / A Simple Example
The new way that can watch multiple paths - for versions 1.x and higher:
fswatch -o ~/path/to/watch | xargs -n1 -I{} ~/script/to/run/when/files/change.sh
Note: The number output by -o will get added to the end of the xargs command if not for the -I{}. If you do choose to use that number, place {} anywhere in your command.
The older way for versions 0.x:
fswatch ~/path/to/watch ~/script/to/run/when/files/change.sh
Installation with Homebrew
As of 9/12/13 it was added back in to homebrew - yay! So, update your formula list (brew update) and then all you need to do is:
brew install fswatch
Installation without Homebrew
Type these commands in Terminal.app
cd /tmp
git clone https://github.com/alandipert/fswatch
cd fswatch/
make
cp fswatch /usr/local/bin/fswatch
If you don't have a c compiler on your system you may need to install Xcode or Xcode command line tools - both free. However, if that is the case, you should probably just check out homebrew.
Additional Options for fswatch version 1.x
Usage:
fswatch [OPTION] ... path ...
Options:
-0, --print0 Use the ASCII NUL character (0) as line separator.
-1, --one-event Exit fsw after the first set of events is received.
-e, --exclude=REGEX Exclude paths matching REGEX.
-E, --extended Use exended regular expressions.
-f, --format-time Print the event time using the specified format.
-h, --help Show this message.
-i, --insensitive Use case insensitive regular expressions.
-k, --kqueue Use the kqueue monitor.
-l, --latency=DOUBLE Set the latency.
-L, --follow-links Follow symbolic links.
-n, --numeric Print a numeric event mask.
-o, --one-per-batch Print a single message with the number of change events.
in the current batch.
-p, --poll Use the poll monitor.
-r, --recursive Recurse subdirectories.
-t, --timestamp Print the event timestamp.
-u, --utc-time Print the event time as UTC time.
-v, --verbose Print verbose output.
-x, --event-flags Print the event flags.
See the man page for more information.
You can use launchd for that purpose. Launchd can be configured to automatically launch a program when a file path is modified.
For example the following launchd config plist will launch the program /usr/bin/logger when the desktop folder of my user account is modified:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>logger</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/logger</string>
<string>path modified</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Users/sakra/Desktop/</string>
</array>
</dict>
</plist>
To activate the config plist save it to the LaunchAgents folder in your Library folder as "logger.plist".
From the shell you can then use the command launchctl to activate the logger.plist by running:
$ launchctl load ~/Library/LaunchAgents/logger.plist
The desktop folder is now being monitored. Every time it is changed you should see an output in the system.log (use Console.app).
To deactivate the logger.plist, run:
$ launchctl unload ~/Library/LaunchAgents/logger.plist
The configuration file above uses the WatchPaths option. Alternatively you can also use the
QueueDirectories option. See the launchd man page for more information.
Facebook's watchman, available via Homebrew, also looks nice. It supports also filtering:
These two lines establish a watch on a source directory and then set
up a trigger named "buildme" that will run a tool named "minify-css"
whenever a CSS file is changed. The tool will be passed a list of the
changed filenames.
$ watchman watch ~/src
$ watchman -- trigger ~/src buildme '*.css' -- minify-css
Notice that the path must be absolute.
You might want to take a look at (and maybe expand) my little tool kqwait. Currently it just sits around and waits for a write event on a single file, but the kqueue architecture allows for hierarchical event stacking...
watchdog is a cross-platform python API for watching files / directories, and it has builtin "tricks" tool that allows you to trigger actions (including shell commands) when events occur (including new added file, removed file and changed file).
This is just to mention entr as an alternative on OSX to run arbitrary commands when files change. I find it simple and useful.
brew install entr on macos
apt install entr on Debian/Ubuntu
Here's a one-liner using sschober's tool.
$ while true; do kqwait ./file-to-watch.js; script-to-execute.sh; done
Apple OSX Folder Actions allow you to automate tasks based on actions taken on a folder.
Edit: fsw has been merged into fswatch. In this answer, any reference to fsw should now read fswatch.
I wrote an fswatch replacement in C++ called fsw which features several improvements:
It's a GNU Build System project which builds on any supported platform (OS X v. >= 10.6) with
./configure && make && sudo make install
Multiple paths can be passed as different arguments:
fsw file-0 ... file-n
It dumps a detailed record with all the event information such as:
Sat Feb 15 00:53:45 2014 - /path/to/file:inodeMetaMod modified isFile
Its output is easy to parse so that fsw output can be piped to another process.
Latency can be customised with -l, --latency.
Numeric event flags can be written instead of textual ones with -n, --numeric.
The time format can be customised using strftime format strings with -t, --time-format.
The time can be the local time of the machine (by default) or UTC time with -u, --utc-time.
Getting fsw:
fsw is hosted on GitHub and can be obtained cloning its repository:
git clone https://github.com/emcrisostomo/fsw
Installing fsw:
fsw can be installed using the following commands:
./configure && make && sudo make install
Further information:
I also wrote an introductory blog post where you can find a couple of examples about how fsw works.
My fork of fswatch provides the functionality of inotifywait -m with slightly less (no wait, more! I have a lot more troubles on Linux with inotifywait...) parse-friendly output.
It is an improvement upon the original fswatch because it sends out the actual path of the changed file over STDOUT rather than requiring you to provide a program that it forks.
It's been rock solid as the foundation of a series of scary bash scripts I use to automate stuff.
(this is off-topic) inotifywait on Linux, on the other hand, requires a lot of kludges on top of it and I still haven't figured out a good way to manage it, though I think something based on node.js might be the ticket.
I have a GIST for this and the usage is pretty simple
watchfiles <cmd> <paths...>
To illustrate, the following command will echo Hello World every time that file1 OR file2 change; and the default interval check is 1 second
watchfiles 'echo Hello World' /path/to/file1 /path/to/file2
If I want to check every 5 seconds I can use the -t flag
watchfiles -t 'echo Hello World' /path/to/file1 /path/to/file2
-v enables the verbose mode which shows debug information
-q makes watchfiles execute quietly (# will be shown so the user can see the program is executing)
-qq makes watchfiles execute completely quietly
-h shows the help and usage
https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55
I ended up doing this for macOS. I'm sure this is terrible in many ways:
#!/bin/sh
# watchAndRun
if [ $# -ne 2 ]; then
echo "Use like this:"
echo " $0 filename-to-watch command-to-run"
exit 1
fi
if which fswatch >/dev/null; then
echo "Watching $1 and will run $2"
while true; do fswatch --one-event $1 >/dev/null && $2; done
else
echo "You might need to run: brew install fswatch"
fi
If you want to use NodeJS, you can use a package called chokidar (or chokidar-cli actually) for the watching and then use rsync (included with Mac):
Rsync command:
$ rsync -avz --exclude 'some-file' --exclude 'some-dir' './' '/my/destination'
Chokidar cli (installed globally via npm):
chokidar \"**/*\" -c \"your-rsync-command-above\"
sudo fs_usage -f filesys | grep "interesting thing" ?
I can wholeheartedly recommend using watchexec. Built in Rust and It Just Works™ no matter which platform you're on! Straightforward CLI options as well.
Here's a simple single line alternative for users who don't have the watch command who want to execute a command every 3 seconds:
while :; do your-command; sleep 3; done
It's an infinite loop that is basically the same as doing the following:
watch -n3 your-command
I have this bash script that loops through the files in the current directory and extracts the date part from the filename, then uses (Unix) touch command to modify (or update) that file's modification-date (mtime) to this date.
Filename example
Electric company name - bill - 2014-03-22.pdf
Bash script:
I save this bash script as _save_file_mtime_from_filename.sh (add chmod +x to it) and put in the directory where I'd like to change the file's modification time. And then run it from the command-line.
#!/bin/bash
CURRENT_DIR=$(dirname $_)
cd $CURRENT_DIR
for f in *
do
# Strip the file extension
d=${f%.*}
# Strip the last 10 characters
d=${d:${#d}-10}
# Check the format / mask
if [[ $d = ????-??-?? ]] ; then
# Strip the dash
d=${d//-}
# Run `touch` on the file with the extracted date format
# and add `0000` to the file date
touch -t ${d}0000 "$f"
fi
done
Now I'm searching for a Windows version of this script
I've search the net (and Stackoverflow). Found some related questions like https://stackoverflow.com/questions/51435/windows-version-of-the-unix-touch-command and https://superuser.com/questions/251470/windows-recursive-touch-command/251507#251507
Does anyone have any idea for a Windows version using a _save_file_mtime_from_filename.bat executable version that does essentially the same thing?
With a little tweaking and help of a (Mac) Automator action, saved as an 'application', you can even trigger this script in the Mac Finder from the right-mouse button (https://discussions.apple.com/thread/5287944?start=15&tstart=0). Sweet!
Install Cygwin, or install binaries from GnuWin32 or UnixUtils
I agree with #konsolebox. Just install Cygwin, and you can run your script with no changes.
However, if you don't want to go that route, you should be able to install "coreutils" from GnuWin32. Coreutils contains "touch", among other things. Writing a DOS batch file to emulate what you've written above might be a little painful, though. The part that looks tricky to me is [[ $d = ????-??-?? ]]. You'll have to do something creative to match that, perhaps using grep, which you can get from the same page. Now you're installing a couple things, and doing a lot of work, though. Installing Cygwin would be easier.
How to create a bash file?
I found following bash script.
#!/bin/bash
for f in *.wav; do
echo "Processing $f file..."
afconvert -f caff -d LEI16#44100 -c 1 "$f" "${f/wav/caf}"
done
I have Mac and Windows.
But I don't know where I have to put this and how I can run this script?
Just save the text into a file called my_bash_script a file, make it executable and run it from the command line like this:
chmod u+x my_bash_script
./my_bash_script
Judging by the file it will need to be in a directory containing *.wav files.
As you have two different OS setup, I will split my answer in two parts.
First: Windows
Windows does not have a Bash interpreter, nor the afconvert program the code above is trying tu run. Your best bet will be to use Cygwin to install a Unix console on your Windows. Also I don't know, where you could get afconvert from.
OSX
OSX does have a console and the afconvert software (at least my OSX does). You can simply drop the file in a folder and give it a name ending in .sh. Then you should be able to run it.
Just paste the text into a plaint text file and then mark it as executable:
chmod +x yourScript
To run it:
./yourScript
Place the script anywhere you have your .wav files. When fallow instructions given here:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html#sect_02_01_03
I want to watch a folder on my Mac and then execute a bash script, passing it the name of whatever file/folder was just moved into or created in the watched directory.
fswatch
fswatch is a small program using the Mac OS X FSEvents API to monitor a directory.
When an event about any change to that directory is received, the specified
shell command is executed by /bin/bash
If you're on GNU/Linux,
inotifywatch (part of the
inotify-tools package on most distributions) provides similar
functionality.
Update: fswatch can now be used across many platforms including BSD, Debian, and Windows.
Syntax / A Simple Example
The new way that can watch multiple paths - for versions 1.x and higher:
fswatch -o ~/path/to/watch | xargs -n1 -I{} ~/script/to/run/when/files/change.sh
Note: The number output by -o will get added to the end of the xargs command if not for the -I{}. If you do choose to use that number, place {} anywhere in your command.
The older way for versions 0.x:
fswatch ~/path/to/watch ~/script/to/run/when/files/change.sh
Installation with Homebrew
As of 9/12/13 it was added back in to homebrew - yay! So, update your formula list (brew update) and then all you need to do is:
brew install fswatch
Installation without Homebrew
Type these commands in Terminal.app
cd /tmp
git clone https://github.com/alandipert/fswatch
cd fswatch/
make
cp fswatch /usr/local/bin/fswatch
If you don't have a c compiler on your system you may need to install Xcode or Xcode command line tools - both free. However, if that is the case, you should probably just check out homebrew.
Additional Options for fswatch version 1.x
Usage:
fswatch [OPTION] ... path ...
Options:
-0, --print0 Use the ASCII NUL character (0) as line separator.
-1, --one-event Exit fsw after the first set of events is received.
-e, --exclude=REGEX Exclude paths matching REGEX.
-E, --extended Use exended regular expressions.
-f, --format-time Print the event time using the specified format.
-h, --help Show this message.
-i, --insensitive Use case insensitive regular expressions.
-k, --kqueue Use the kqueue monitor.
-l, --latency=DOUBLE Set the latency.
-L, --follow-links Follow symbolic links.
-n, --numeric Print a numeric event mask.
-o, --one-per-batch Print a single message with the number of change events.
in the current batch.
-p, --poll Use the poll monitor.
-r, --recursive Recurse subdirectories.
-t, --timestamp Print the event timestamp.
-u, --utc-time Print the event time as UTC time.
-v, --verbose Print verbose output.
-x, --event-flags Print the event flags.
See the man page for more information.
You can use launchd for that purpose. Launchd can be configured to automatically launch a program when a file path is modified.
For example the following launchd config plist will launch the program /usr/bin/logger when the desktop folder of my user account is modified:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>logger</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/logger</string>
<string>path modified</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Users/sakra/Desktop/</string>
</array>
</dict>
</plist>
To activate the config plist save it to the LaunchAgents folder in your Library folder as "logger.plist".
From the shell you can then use the command launchctl to activate the logger.plist by running:
$ launchctl load ~/Library/LaunchAgents/logger.plist
The desktop folder is now being monitored. Every time it is changed you should see an output in the system.log (use Console.app).
To deactivate the logger.plist, run:
$ launchctl unload ~/Library/LaunchAgents/logger.plist
The configuration file above uses the WatchPaths option. Alternatively you can also use the
QueueDirectories option. See the launchd man page for more information.
Facebook's watchman, available via Homebrew, also looks nice. It supports also filtering:
These two lines establish a watch on a source directory and then set
up a trigger named "buildme" that will run a tool named "minify-css"
whenever a CSS file is changed. The tool will be passed a list of the
changed filenames.
$ watchman watch ~/src
$ watchman -- trigger ~/src buildme '*.css' -- minify-css
Notice that the path must be absolute.
You might want to take a look at (and maybe expand) my little tool kqwait. Currently it just sits around and waits for a write event on a single file, but the kqueue architecture allows for hierarchical event stacking...
watchdog is a cross-platform python API for watching files / directories, and it has builtin "tricks" tool that allows you to trigger actions (including shell commands) when events occur (including new added file, removed file and changed file).
This is just to mention entr as an alternative on OSX to run arbitrary commands when files change. I find it simple and useful.
brew install entr on macos
apt install entr on Debian/Ubuntu
Here's a one-liner using sschober's tool.
$ while true; do kqwait ./file-to-watch.js; script-to-execute.sh; done
Apple OSX Folder Actions allow you to automate tasks based on actions taken on a folder.
Edit: fsw has been merged into fswatch. In this answer, any reference to fsw should now read fswatch.
I wrote an fswatch replacement in C++ called fsw which features several improvements:
It's a GNU Build System project which builds on any supported platform (OS X v. >= 10.6) with
./configure && make && sudo make install
Multiple paths can be passed as different arguments:
fsw file-0 ... file-n
It dumps a detailed record with all the event information such as:
Sat Feb 15 00:53:45 2014 - /path/to/file:inodeMetaMod modified isFile
Its output is easy to parse so that fsw output can be piped to another process.
Latency can be customised with -l, --latency.
Numeric event flags can be written instead of textual ones with -n, --numeric.
The time format can be customised using strftime format strings with -t, --time-format.
The time can be the local time of the machine (by default) or UTC time with -u, --utc-time.
Getting fsw:
fsw is hosted on GitHub and can be obtained cloning its repository:
git clone https://github.com/emcrisostomo/fsw
Installing fsw:
fsw can be installed using the following commands:
./configure && make && sudo make install
Further information:
I also wrote an introductory blog post where you can find a couple of examples about how fsw works.
My fork of fswatch provides the functionality of inotifywait -m with slightly less (no wait, more! I have a lot more troubles on Linux with inotifywait...) parse-friendly output.
It is an improvement upon the original fswatch because it sends out the actual path of the changed file over STDOUT rather than requiring you to provide a program that it forks.
It's been rock solid as the foundation of a series of scary bash scripts I use to automate stuff.
(this is off-topic) inotifywait on Linux, on the other hand, requires a lot of kludges on top of it and I still haven't figured out a good way to manage it, though I think something based on node.js might be the ticket.
I have a GIST for this and the usage is pretty simple
watchfiles <cmd> <paths...>
To illustrate, the following command will echo Hello World every time that file1 OR file2 change; and the default interval check is 1 second
watchfiles 'echo Hello World' /path/to/file1 /path/to/file2
If I want to check every 5 seconds I can use the -t flag
watchfiles -t 'echo Hello World' /path/to/file1 /path/to/file2
-v enables the verbose mode which shows debug information
-q makes watchfiles execute quietly (# will be shown so the user can see the program is executing)
-qq makes watchfiles execute completely quietly
-h shows the help and usage
https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55
I ended up doing this for macOS. I'm sure this is terrible in many ways:
#!/bin/sh
# watchAndRun
if [ $# -ne 2 ]; then
echo "Use like this:"
echo " $0 filename-to-watch command-to-run"
exit 1
fi
if which fswatch >/dev/null; then
echo "Watching $1 and will run $2"
while true; do fswatch --one-event $1 >/dev/null && $2; done
else
echo "You might need to run: brew install fswatch"
fi
If you want to use NodeJS, you can use a package called chokidar (or chokidar-cli actually) for the watching and then use rsync (included with Mac):
Rsync command:
$ rsync -avz --exclude 'some-file' --exclude 'some-dir' './' '/my/destination'
Chokidar cli (installed globally via npm):
chokidar \"**/*\" -c \"your-rsync-command-above\"
sudo fs_usage -f filesys | grep "interesting thing" ?
I can wholeheartedly recommend using watchexec. Built in Rust and It Just Works™ no matter which platform you're on! Straightforward CLI options as well.
Here's a simple single line alternative for users who don't have the watch command who want to execute a command every 3 seconds:
while :; do your-command; sleep 3; done
It's an infinite loop that is basically the same as doing the following:
watch -n3 your-command