New answers tagged

4

Use sort | uniq -c to count identical lines: find "$path" -type f -exec file -b {} + | sort | uniq -c | sort -nr


1

Bash 4 solution utilizing associative arrays and for environments with the zero delimiter extensions. First parameter is the target directory, all following parameters are forwarded to file: #!/bin/bash # USAGE: script.sh PATH [PARAMS_FOR_FILE_CMD...] # EXAMPLE 1: ./script.sh . # EXAMPLE 2: ./script.sh /tmp --mime-type path=$1 shift declare -A ...


2

The ? is part of a mechanism called "pathname expansion" in the shell. Colloquially, the mechanism is called globing. The basic glob makes use just of three characters: * ? and [ that build "patterns". An asterisk * means: Any character in any quantity. (any string). An interrogation character ? means: Any character one time. The square brace ...


2

? is a special character in pattern matching, which match any single character. So the command means find all files and directories in /foo/path and its subdirectories, whose names are exactly one character long. The \? is used to prevent your shell from performing filename generation. You can use other quoting mechanisms: find /foo/path -name '?' or: ...


0

While there are good answers already here, I find this more intuitive, within bash: find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \; Where aaa is your existing directory. The files it contains will be moved to the current directory (leaving only empty directories in aaa). The two calls to tr handle both ...


0

In zsh (and most non-Bourne derived shells), when a (or all depending on the shell) glob doesn't expand, the command is aborted. $(do_something to find filenames) is not a glob, but you can make it become one by appending a glob qualifier in zsh: find $(do_something to find filenames)(#q) -print0... Above, that (#q) (an empty glob qualifier, so does ...


4

With zsh, I'd do: files=($(do_something to find filenames)) (($#files)) && find $files ... With tcsh: set files=(`do_something to find filenames`) if ($#files) find $files:q ... With bash, mksh or ksh93, set -f; files=($(do_something to find filenames)) ((${#files[@]})) && find "${files[@]}" ... POSIXly: set -f; set -- ...


3

How about doing this: paths=$(do_something to find filenames) if [ "$paths" ]; then find "$paths" ... fi This works independent from the find implementation. Note that find "$paths" with more than a single path name causes problems. If the path names do not contain spaces, you may use: find $paths, otherwise, a working alternative is this function: ...


0

You can give find an extra, non-existant directory to start from: find " " $(do_something to find filenames) -print0 | xargs -r0 ls -ld To make this tidy, drop find's error output: find " " $(do_something to find filenames) -print0 2>/dev/null | xargs -r0 ls -ld (but then you won't notice if another error occurs...). When do_something to find ...


0

find ... -execdir command {} + doesn't do anything like that. It works exactly the same as find ... -exec except that find first changes directory to the dir that the matching file(s) are in before executing the command. Run man find (or if using GNU find, info find or pinfo find for more detailed documentation) and search for -execdir. From the GNU find ...


1

+ is the end marker , {} is replaced with the filenames the current directory is the path. so $PWD = /home/jesse/hacking/sh_sandbox/ $0 = /home/jesse/hacking/sh_sandbox/save_params.sh $1 = ./zero_param.txt $2 = ./first_param.txt $3 = ./second_param.txt $4 = ./third_param.txt or something like that... re-reading the question it seems that the script is ...


1

Based on L.Levrel response, using the tools supplied in OS X (this should also work in Ubuntu). find . -type f -name '*.pdf' -exec grep -alE '/Producer \(pdfTeX|/Producer\(pdfTeX' {} +


3

You can look at the "/Producer" line: find -name '*.pdf' | xargs grep -al '^/Producer (pdfTeX' or with double quotes find -name '*.pdf' | xargs grep -al "^/Producer (pdfTeX" or with null-separated list of files find -name '*.pdf' -print0 | xargs -0 grep -al '^/Producer (pdfTeX'


0

This is a real bug found in find version 4.4.2, but the bug has been fixed in find version 4.6.0.


0

rename doesn't support regex on my distro. I have to use perl-rename. I am assuming that you're running the above command from a directory above the one in question.


0

Try using the -delete command for simplicity: find -L /archive -type f -print -delete It will be faster and also spawn less sub-processes.


0

If you're using GNU find you can do this find /archive -type f -delete


2

I found the problem. It seems that locate is fast because it relies upon a database it builds to search for things faster. This database is updated daily. The updatedb command does this. As it turns out, updatedb is run every 24 hours, and 24 hours hadn't passed when I tried to search for the file using locate, from the time the file was created. After ...


-1

I don't use or know much about 'locate(1)'. But 'find(1)' may be failing to find your command because it does not by default cross filesystem lines. The makeinfo command is likely in /usr/bin (type which makeinfo to find it), and the '/usr' partition may be on another filesystem. EDIT: Doh! I see the problem! do not use "*makeinfo*". Use 'makeinfo'. If you ...


0

Assuming you are using GNU tar, you can say: tar --transform 's/.*\///' -xzf archive.tgz This will strip everything up to the last slash from the file names.


0

You've got this error: dirname: missing operand. Try dirname --help' for more information because dirname has missing operand (nothing was passed as an argument). This happened, because grep returned empty results. If you're using GNU xargs, you can use -r (--no-run-if-empty) to not run the command, when input is empty (does not contain any ...


3

dirname of file is missing in first part, try grep -w 'sucessfully completed.' "/var/log/folder/$(ls -1rt /var/log/folder | tail -n1)" do not try ... unles there is no dir in /var/log/folder/ grep -w 'sucessfully completed.' "$(ls -1rt /var/log/folder/* | tail -n1)"


4

Here is a version that is safe for names with whitespace: find /var/log/folder -type f -printf '%T@ %p\0' | sort -rz | sed -Ezn '1s/[^ ]* //p' | xargs --null grep string How it works: find /var/log/folder -type f -printf '%T@ %p\0' This looks for files and prints their modification time (seconds) followed by a space and their name followed by a nul ...


3

ls -1rt /path/to/files/ | tail -n1 will find the newest file in a directory (in terms of modification time); pass that as an argument to grep: grep 'string to find' "$(ls -1rt /path/to/files/ | tail -n1)"


2

As others have identified, the problem with your command is that it includes directories, and tar archives them recursively. If a directory has been modified recently, all the files in it and its subdirectories get included, whether they have been modified or not. If you don't care to back up directory metadata, then just tell find not to print directory ...


2

You will not only run into problems if xargs invokes tar twice, you also will get problems if your file-names contain special characters like newlines. You should drop the use of xargs and tar and use find with cpio: find $SOURCEDIR -mtime -1 -print0 | cpio --create -0 --verbose \ --format=ustar -O $ARCHIVE ustar provides you with a POSIX.1 ...


2

find $SOURCEDIR -mtime -1 also includes $SOURCEDIR in the output, which needs to be removed before further processing Using grep -vx one can define a particular line to be excluded.. find $SOURCEDIR -mtime -1 -print | grep -xv "$SOURCEDIR" | xargs -r tar cvf $ARCHIVE || { echo "No files have been changed in the past 24 hours. Exiting script ..." ; exit ...


0

When you execute find $SOURCEDIR -mtime -1 -print it will have as the first result the folder $SOURCEDIR itself. That is why everything is included. You have to exclude the first result or $SOURCEDIR.


3

You can use the rename command (see edit 1). Solution 1 For a reasonable number of files/directory, by setting bash 4 option globstar (not works on recursive name, see edit 3): shopt -s globstar rename -n 's/etckeeper/userkeeper/g' ** Solution 2 For a big number of files/directories using rename and find in two steps to prevent failed rename on files ...


0

Another solution is to use a small script and do a for loop on the find results and a mv with a bash string replacement on the files found : IFS=$'\n' for files in $(find . -name "*etckeeper*"); do mv "$files ${files/etckeeper/usrkeeper}" done If you don't use it in the script, then better save the original IFS and restore it at the end of the loop. ...


0

Your original question is actually pretty easy to answer: xargs (at least on OS X) has an -I option, too, which does not require that the replacement string be a unique argument. So, the invocation simply becomes: % find . -path '*etckeeper*' -print0 | xargs -0 -n 1 -I % bash -c 'echo mv % $(echo % | sed "s/etckeeper/usrkeeper/g" )' Easy peasy. Now, let's ...


2

Your use of 'parent folder' is a little confusing, this will find all the folders (actually directories) in a given path, without traversing the entire tree, that are made up only of A-Z. find /given/path -type d -maxdepth 1 -regextype sed -regex ".*/[A-Z]*" For example, to do the current directory, find . -maxdepth 1 -type d -regextype sed -regex ...


0

Try the following command: ls -1 | grep -w "[A-Z]*"


2

Iterating over the subdirectories of a directory: for subdir in root_folder/*/; do if [ -L "${subdir%/}" ]; then continue; fi … done The if [ -L … line skips symbolic links to directories. Omit it if you want to include symbolic links to directories or if you know there won't be any. Directories whose name begins with a . (dot directories) won't be ...


3

Below script works for your case : find . -mindepth 1 -maxdepth 1 -type d -print0 | while read -rd '' line do files=("$line"/* "$line"/.*) count=${#files[@]};((count-=2)) if [ $count -ge 5 ] then cp -R "$line" ../newfolder/ fi done Note : This should be executed from the base folder as I am using relative paths.


4

You can do a for loop on the find result and copy the folder with -R : IFS=$'\n' for source_folder in "$(find . -maxdepth 1 -type d -exec bash -c "echo -ne '{}\t'; ls '{}' | wc -l" \; | awk -F"\t" '$NF>=5{print $1}');" do if [[ "$source_folder" != "." ]]; then cp -R "$source_folder" /destination/folder fi done


2

No. You need to use -o (OR) in find like: find \( -iname '*.jpg' -o -iname '*.png' \) Your one would be close to correct if you are matching Regex: find -iregex ".*\(jpg\|png\)" Or using extended Regex: find -regextype posix-extended -iregex ".*(jpg|png)"


1

Using sed: sed -i.bak 's#^\(GLOBAL_PATH=/export/\)pop/PLW5$#\1lld/sat#' /var/userTN/applo/* The original file(s) will be backup up with .bak extension, if you don't want backup(s): sed -i 's#^\(GLOBAL_PATH=/export/\)pop/PLW5$#\1lld/sat#' /var/userTN/applo/* Example: $ sed 's#^\(GLOBAL_PATH=/export/\)pop/PLW5$#\1lld/sat#' ...


3

Is this what you mean? find ~/ops_scripts -type f -maxdepth 1 -name "*ScheduledJobs*.txt"


2

From the find(1) manpage: The -H, -L and -P options control the treatment of symbolic links. Command-line arguments following these are taken to be names of files or directories to be examined, up to the first argument that begins with -, or the argument ( or !. That argument and any following arguments are taken to ...


0

find */ -type f -mtime -30 -print0 | sed -z -e 's:/.*$::' | sort -z -u | tr '\000' '\n' Requires GNU sort and GNU sed for the -z (NUL-separated input) options. find lists all files in subdirectories of the current directory less than 30 days old. output is piped into sed to remove everything after the first /, then into sort to unique ...


0

find ./ | grep " " will get you the files and directories contains spaces find ./ -type f | grep " " will get you the files contains spaces find ./ -type d | grep " " will get you the directories contains spaces


1

I would use find on each directory in turn, and pipe it to grep -q . to check if there are any results, and print the directory name conditionally upon whether or not there were any results: for d in */; do find "$d" -type f -mtime -30 | grep -q . && printf %s\\n "$d"; done


1

This might be not efficient but I hope it could help you find -mindepth 3 -maxdepth 3 -type f -mtime -30 | xargs -n 1 dirname | xargs -n 1 dirname | uniq # (or sort -u, I assume find's output is already sorted)


0

I'd use something more like your last approach, such as for d in $(find httpdocs -type d -name backup) do ls -t $d | grep '.xml$' | head -1 done ls -t sorts by modified time, most recent first. If you want the full pathname in the output, you can use ls -t $d/*.xml and skip the grep. There are simple but non-obvious ways to shorten the pathname if you ...


2

You can try this one using find and grep : find . -type f -name '*.php' -exec grep '.\{1000\}' {} +


7

You can do it with just find and awk: find . -type f -name '*.php' -size +1000c -exec awk ' FNR > 1 {nextfile} length >= 1000 {print FILENAME}' {} + The awk script skips to next file after the first line of every file. It prints the filename of the current file if the current line is >= 1000 characters long.


0

Replacing in files Your command isn't reliable for several reasons: it excludes all paths containing .git as a substring, it doesn't work with paths containing whitespace or \'", it replaces input with any character between com and foo. The last problem is easily solved by adding a backslash before the dot. The problems with file names may or may not be an ...


1

1 For your first step, in your command example, you do not need the * because that is not filtering any file. What you do need is to filter .git, as this: $ find . -name '.git' -prune -o -type f -print That will reject (-prune) any directory exactly named .git and everything inside it. That removes the need of grep -v ".git". The sed could not be ...


1

Try: ( cd ~/.jenkins/jobs/subco find . -path ./myapp -prune -o -type f -name '*.jar' -print0 | ... ) Adding -type f to restrict the condition, since when you want to match JAR files only. And also, you used -print0, it's likely that your find supports -delete, so you can use: ( cd ~/.jenkins/jobs/subco find . -path ./myapp -prune -o -type f -name ...



Top 50 recent answers are included