was want to search for a specific file on my server and directly edit it within nano.
i tried it like this, but it wont work
find -name file.php | xargs nano $1
the file is found, but it wont work like that
Received SIGHUP or SIGTERM
how to do that proberly?
Another solution is to use backticks if you have to use other command. It's for example useful with git status:
nano `git status | grep modified | awk '{ print $2 }'`
Or, with find:
nano $(find -name file\*.php)
i found the solution in using find intern exec function
# find -name file.php -exec nano {} \;
Related
I have a bunch of files that I want to find with find. Then I want to run a command (which outputs to STDOUT) and write this to a new file with an appended extension. This is what I have so far:
find . -name "*.txt" -exec command -O -I{} > {}.nav \;
So say that find gives me the file list:
./1/file1.txt
./2/file2.txt
I would like to have the result:
./1/file1.txt
./1/file1.txt.nav
./2/file2.txt
./2/file2.txt.nav
But I'm only getting one new file which all content has been concatenate to called {}.nav. Any tips on how I should proceed?
you can try the below, using tee command
for file in $(find . -name "*.txt"); do <command> "$file" | tee "$file".nav; done
from man tee
tee - read from standard input and write to standard output and files
How about using awk with find as follows, if I understood your requirement correctly.
find -type f -name "*.txt" | awk '{print $0 ORS $0".nav"}'
There is a way to acheive the desired result without using a for loop by using bash and tee. Since find outputs the results to stdout for each file found, you are still going to need to use tee. For example if you wanted to grep all lines with the value "HelloWorld" for each file and output the results into a separate file you can run the command below:
find . -name "*.txt" -exec bash -c 'grep "HelloWorld" {} | tee "{}.nav"' \;
As you can see the command above does not require a for loop but still produces the desired result. Please accept this as the answer as it directly answers your question but also omits the for loop in #nullPointer's answer.
I have a bash script I cannot get working. I am a dead set beginner in bash this is actually the first script I've ever used. I'm trying to get omxplayer to play a list of files in a directory. When the script runs I get feedback showing the file then the error that there is no such file or directory. Please help me?
#!/bin/sh
find /media/pi/88DC-E668/MP3/ -name "*.mp3" -exec PLAY={} \;; omxplayer "$PLAY";
This is the echo:
find: `PLAY=/media/pi/88DC-E668/MP3/Dance.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Whitemary.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Limo.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Silo.mp3': No such file or directory
File "" not found.
Easy way:
find /media/pi/88DC-E668/MP3 -name \*.mp3 -exec omxplayer {} \;
or
while IFS= read -r -d '' mp3
do
omxplayer "$mp3"
done < <(find /media/pi/88DC-E668/MP3 -name \*.mp3 -print0)
or
find /media/pi/88DC-E668/MP3 -name \*.mp3 -print0 | xargs -0 -n1 omxplayer
You can omit the -n1 if the omxplayer could handle multiple filenames. In such case the 1st could be written as:
find /media/pi/88DC-E668/MP3 -name \*.mp3 -exec omxplayer {} +
but the simplest probably will be
#shopt -s globstar #the default is on
for mp3 in /media/pi/88DC-E668/MP3/{,**/}*.mp3
do
omxplayer "$mp3"
done
EDIT I stand corrected, but won't delete the answer as you can also learn from the mistakes of others. See comment and rather use this answer :)
So please don't do it like this, as this is a typical "happy path" solution - meaning: it works if you know what you're doing and you know your paths (e.g. that they don't contain spaces). I keep forgetting that many people don't know yet that spaces in paths are evil.
Just use xargs to pass what you found to your player like this:
#!/bin/sh
find /media/pi/88DC-E668/MP3/ -name "*.mp3" | xargs omxplayer
The -exec foo part means run the command foo for each path found.
In your case, -exec PATH={}, the {} part is replaced with the path name, ending up with something like -exec PATH=/media/pi/88DC-E668/MP3/Dance.mp3, and so then find tries to run the command PATH=/media/pi/88DC-E668/MP3/Dance.mp3 which fails because there isn't actually any such program to execute.
xargs is the usual way to do what you're trying to do, as described in another comment already.
You could also do:
find /media/pi/88DC-E668/MP3/ -name \*.mp3 |
while read f; do
omxplayer "$f"
done
I want add some script to my site.
But problem in one thing: site include hundreds of html files.
So I need to create some command to insert code after body tag. How I can do this?
find . -name '*.html' exec sed -i 's/<\/body>/<script src="1.js"><\/script><\/body>/g' {} \;
But it can't work.
Please, fix this command
There is an error in command - replace exec with -exec and should be fine.
find . -name '*.html' exec sed -i 's/<\/body>/<script src="1.js"><\/script><\/body>/g' {} \;
That also works for me:
find * -name "*.html" | xargs -L1 -I{} sed -i 's/<\/body>/<script src="1.js"><\/script><\/body>/g' {}
Changes:
replaced path . with '*'
the'xargs' tool gets all lines from stdin, and executes command separately for each of line, with possibility to pass that line as argument in command, so
in that case this is the same approach as find -cmd, but generally it opens another possibilites (check out the xargs manual).
I'm trying to run the expand shell command on all files found by a find command. I've tried -exec and xargs but both failed. Can anyone explain me why? I'm on a mac for the record.
find . -name "*.php" -exec expand -t 4 {} > {} \;
This just creates a file {} with all the output instead of overwriting each individual found file itself.
find . -name "*.php" -print0 | xargs -0 -I expand -t 4 {} > {}
And this just outputs
4 {}
xargs: 4: No such file or directory
Your command does not work for two reasons.
The output redirection is done by the shell and not by find. That means that the shell will redirect finds output into the file {}.
The redirection would occur immediately. That means that the file will be written even before it is read by the expand command. So it's not possible to redirect a command's output into the input file.
Unfortunately expand doesn't allow to write it's output into a file. So you have to use output redirection. If you use bash you could define a function that executes expand, redirects the output into a temporary file and move the temporary file back over the original file. The problem is that find will run a new shell to execute the expand command.
But there is a solution:
expand_func () {
expand -t 4 "$1" > "$1.tmp"
mv "$1.tmp" "$1"
}
export -f expand_func
find . -name \*.php -exec bash -c 'expand_func {}' \;
You are exporting the function expand_func to sub shells using export -f. And you don't execute expand itself using find -exec but you execute a new bash that executes the exported expand_func.
'expand' isn't really worth the trouble.
You can just use sed instead:
find . -name "*.php" | xargs sed -i -e 's/\t/ /g'
Once I am in the directory containing .mp3 files, I can play songs randomly using
mpg123 -Z *.mp3
But if I want to recursively search a directory and its subfolders for .mp3 files and play them randomly, I tried following command, but it does not work.
mpg123 -Z <(find /media -name *.mp3)
(find /media -name *.mp3), when executed gives all .mp3 files present in /media and its sub directories.
How can I get this to work?
mpg123 -Z $(find -name "*.mp3")
The $(...) means execute the command and paste the output here.
Also, to bypass the command-line length limit laalto mentioned, try:
mpg123 -Z $(find -name "*.mp3" | sort --random-sort| head -n 100)
EDIT: Sorry, try:
find -name "*.mp3" | sort --random-sort| head -n 100|xargs -d '\n' mpg123
That should cope with the spaces correctly, presuming you don't have filenames with embedded newlines.
It will semi-randomly permute your list of MP3s, then pick the first 100 of the random list, then pass those to mpg123.
In both zsh and bash 4.0,
mpg123 -Z **/*.mp3
(Bash users will probably need to shopt -s globstar first.)
Backticks.
mpg123 -Z `find /media -name \*.mp3`
Though if you have a lot of files, you may encounter command line length limitations.
Would something like this work?
find /media -name *.mp3 -print0 | xargs -0 mpg123 -Z
The following works fine.
find /media -name "*.mp3" | xargs -d '\n' -n10 mpg123 -Z.
By '-n' option we can provide no. of arguments for a single invocation of command.
Even after I close the terminal where i wrote this command, the songs continue to play as the process mpg123 becomes an orphan and continues to run.
devikasingh#Interest:~$ ps -e | grep mpg123
7239 ? 00:00:01 mpg123
ps -f 7239
UID PID PPID C STIME TTY STAT TIME CMD
1000 7239 1 0 15:21 ? S 0:01 mpg123 -Z /media/MUSIC & PIC/audio_for_you/For You.mp3 /media/MUSIC & PIC/audio_for_you/In My Place.mp3 /
Thanks for the suggestions, By using them I was able to create the following script:
#!/bin/bash song=$(zenity --width=360 --height=320 --title "Select Folder" --file-selection --directory $HOME) find "$song" -name "*.mp3" | sort --random-sort | head -n 100 | xargs -d '\n' mpg123
Probably its better to use xargs, but I use a while loop in bash on Red Hat.
find . -iname "*.mp3" -print | sort -R --random-source=/dev/urandom | while IFS= read -r filename; do play "$filename"; done
The only problem with it is that it is annoying to kill. To kill it, you must hold down Ctrl-C until the while loop is killed.
while...do...done loops through each field in the sort output.
IFS describes the field separators.
IFS= makes each line a single field.
read copies the current field into the filename variable.
The -r option removes backslash processing, which doesn't seem to be necessary on Linux.
play is a simple way of using sox for playback.
I found this one and IMHO, much cleaner than other solutions. I don't own the credits, they goes to site owner.
find $HOME/mp3s -iname '*.mp3' | mpg123 -Z -# -
Found on https://dannyman.toldme.com/2004/12/28/howto-mpg123-random-mp3s/
I just changed from name to iname as sometimes files can have extension in caps...
I tried almost all and when mpg123 is run througth a pipe it returns this error: "Can't get terminal attributes" and I cannot use terminal control keys.
The only way I found to play a list of files found with the command find and be able to use terminal control keys is this (I have directories and files with spaces):
find /media -type f -iname "*.mp3" > /tmp/mp3list
mpg123 -CZvv -# /tmp/mp3list
It looks that mpg123 use the space as separator if you use $(find /media -type f -iname "*.mp3") and in my case doesn't work because I have spaces in all directory's names and in almost all file's names.
This is a script (playmp3.sh) to only execute find when the file doesn't exist:
#!/bin/sh
if ! [ -f /tmp/mp3list ]; then
find /media -type f -iname "*.mp3" > /tmp/mp3list
fi
mpg123 -CZvv -# /tmp/mp3list
I have my library in a separate partition an in my root dir i have this small script that also plays randomly previous song, i have like 40 gb of music, so they almost never repeat.
# !/bin/sh
cd "/media/$USER/7789f483-c7bf-46bc-9293-e8e05dd62199/musik/"
mpg123 -Z */*/*.mp3;