Why doesn't this work? (echo is not the real command)
$ find . -type d -exec echo {} \;
find: missing argument to `-exec'
I managed to do that anyway like this:
$ for f in `find . -type d`; do echo $f; done
This work for me.
find . -type f -exec file '{}' \;
Braces are enclosed in single quote marks to protect them from interpretation as shell script punctuation.
The following line is from the EXAMPLES section of man find:
find . -type f -exec file '{}' \;
It looks to me like the {} part needs to be in single quotes.
Related
I need to find and rename files with question mark in names.
Example: "style.css?ver=111" should become "style.css"
I use this command
find . -type f -name "*\?*" -exec rename 's/\?.*//' '{}' \;
In Debian all works fine, but in CentOS7 I get and error that "rename: not enough arguments
"
Any ideas why?
For a reliable option that should work in any POSIX-compliant system, you may use
find . -type f -name "*\?*" -exec sh -c 'mv -- "$1" "${1%%\?*}"' findshell {} \;
$1 is the name of each file found and ${1%%\?*} is a construct that strips the substring starting from the question mark.
That should be enough if you have a few matching files. If you need it, a more efficient alternative is
find . -type f -name "*\?*" -exec sh -c '
for file in "$#"; do
mv -- "$file" "${file%%\?*}"
done
' findshell {} +
I am trying to run
find . \ -type f -name "*.sh" -exec basename {} \; | sed "s/.sh/ "
to display all files in the currenty directoy, and subdirectories, that end in .sh. I use -exec basename {} to remove the location of the file, so I just get the filenames themselves. The find command is working fine, but when i pipe it into sed "s/.sh/ " I get an error message sed: 1: "s/.sh/ ": unterminated substitute in regular expression. I am trying to replace the .sh extension with nothing, so I just get filenames.
You are only missing the close / on sed.
find . -type f -name "*.sh" -exec basename {} \; | sed "s/\.sh//"
basename can remove the extension for you.
find . -type f -name '*.sh' -exec basename {} .sh \;
Note this will work for all valid file names, not just ones that don't contain a newline.
If your basename command supports it, you can use the -s option to minimize the number of calls to basename you need.
find . -type f -name '*.sh' -exec basename -s .sh {} +
This allows multiple file names to be passed to each call to basename.
In Ruby, I want to shell out the following find command:
find . -type f -name '*.c' -exec mv {} . \;
I have tried many permutations of this command:
system("find . -type f -name '*.c' -exec mv {} . \;")
`find . -type f -name '*.c' -exec mv {} . \;`
%x(find . -type f -name '*.c' -exec mv {} . \;)
But when I run the command, find generates the error message:
find: -exec: no terminating ";" or "+"
I don't think the issue is characters which need to be escaped. This is probably a really simple fix, but any help would be greatly appreciated!
You need - as #mudasobwa indicated - actually pass the backslash to the find command. If you try your string in irb, you see immediately what's going wrong:
>> "find . -type f -name '*.c' -exec mv {} . \;"
=> "find . -type f -name '*.c' -exec mv {} . ;"
However, for actually running your find command, you need to make up your mind, whether system or %x() is the right tool to use. If you want do process the stdout of the command, you have to use %x, and in this case, you have to escape the backslash, because the string is then expended as if it were a string between double quotes:
find_stdout = %x(find . -type f -name '*.c' -exec mv {} . \\;)
If you are not interested in the result, but only in the overall success (exit code,....) of the command, you shhould use system, and in this case, you could use a single quoted string, which permits you to not escape the backslashes:
result = system('find . -type f -name "*.c" -exec mv {} . \;')
Of course, escaping here is not wrong either, and some people recommend for consistency and maintainability to always escape a backslash.
Any idea why this command is not working? btw, I'm trying to strip out the extensions of all csv files in current directory.
find -type f -iname "*.csv" -exec mv {} $(basename {} ".csv") \;
Tried many variants including the parameter expansions, xargs ... Even then all went futile.
This should do:
find ./ -type f -iname "*.csv" -exec sh -c 'mv {} $(basename {} .csv)' \;
find is able to substitute {} with its findings since the quotes prevent executing the subshell until find is done. Then it executes the -exec part.
The problem why yours is not working is that $(basename {} ".csv") is executed in a subshell (-> $()) and evaluated beforehand. If we look at the command execution step-by-step you will see what happens:
find -type f -iname "*.csv" -exec mv {} $(basename {} ".csv") \; - your command
find -type f -iname "*.csv" -exec mv {} {} \; - subshell gets evaluated ($(basename {} ".csv") returns {} since it interprets {} as a literal)
find -type f -iname "*.csv" -exec mv {} {} \; - as you see now: move does actually nothing
First, take care that you have no subdirectories; find, without extra arguments, will automatically recur into any directory below.
Simple approach: if you have a small enough number of files, just use the glob (*) operator, and take advantage of rename:
$ rename 's/.csv$//' *.csv
If you have too many files, use find, and perhaps xargs:
$ find . -maxdepth 1 -type f -name "*.csv" | xargs rename 's/.csv$//'
If you want to be really safe, tell find and xargs to delimit with null-bytes, so that you don't have weird filenames (e.g., with spaces or newlines) mess up the process:
$ find . -maxdepth 1 -type f -name "*.csv" -print0 | xargs -0 rename 's/.csv$//'
I'd like to use find inside a command substitution, where the returned filenames contain whitespace. What option do I need so it correctly quotes the filenames? I tried -print0, but it will not work in the shell itself.
example:
command $(find . -type f) some other params
I also tried with -exec echo "{}" \;, but that was of no help either.
If I use set -x to display shell expansion and the actual command which is executed I get:
$ command `find -type f -printf \"%p\"\ ` some other params
++ find -type f -printf '"%p" '
+ command '"./file_with' 'blanks"' '"./another' 'file"' some other params
Where are the single quotation marks coming from and why are they applied to each "word"?
Put the find result in an array, and run command "${array[#]}" some other params.
Maybe the printf action is more amenable to being contained in a substitution (GNU find only, though):
command $(find . -type f -printf \"%P\"\ ) some other params
The %P placeholder is the filename minus the argument to find, so in cases other than find ., you'd probably want %p instead.
find /what/ever -name "what ever" -exec echo "\{\}" \;
works here (Ubuntu 10.04 default gterm with bash)
Just tried
find /bin -name ls -exec \{\} -lah \;
`find /bin -name ls -exec echo \{\} \;` -lah
MYCMD=`find /bin -name ls -exec echo \{\} \;` && $MYCMD -lah
MYCMD=$(`find /bin -name ls -exec echo \{\} \;` -lah) && echo $MYCMD
MYCMD=$(`find /bin -name ls` -lah) && echo $MYCMD
all work as expected