New answers tagged

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 d -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" -type f That will reject (!) any file named .git. That removes the need of grep -v ".git". The sed could not be avoided, as it is editing the internals of a file, not something ...


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 ...


2

Use the -prune option to skip that directory find ~/.jenkins/jobs/subco -path ~/.jenkins/jobs/subco/myapp -prune -o -name '*.jar' -exec rm -r {} +


1

Implementations of find vary, but they should all handle character classes in wildcards (POSIX.2, section 3.13): find . -name '*[~*]*' If newline is among your "special" characters, you may need to work out how to get your shell to pass it to find. In Bash, you can use find . -name $'*[\t \n]*' to show files containing whitespace, for example. A ...


2

If you want something more general than matching a specific character, you would have to use regular expressions. Since the question is not tagged "linux", the proper answer would use POSIX: find . | grep '[*~]' If you want to make it Linux-specific, you can use the GNU find option -regex (also supported by FreeBSD). If the pathname has an embedded ...


0

You can use the octal forms and do the calculations by hand. With a POSIX shell: dir_perms=$(printf '%#o' "$((0777 - $(umask)))") non_dir_perms=$(printf '%#o' "$((dir_perms & 0666))") find . -type d ! -perms "$dir_perms" -o ! -type d ! -perms "$non_dir_perms" The output format of umask alone is not specified by POSIX but in practice, will all shells, ...


1

Why don't you try this one : find . -user trolkura ! -perm -u+rw This means: look for files starting in present directory, owned by trolkura, where the permissions for group and other can be anything (- in front of permission string) and the users permissions are only: rw


0

If you do this from the working directory, you can do this instead: ls -l |awk '{ if ($8 == "2013") print $9 }' This simplifies things considerably and doesn't cause any overlap. But it also assumes that these files are older than 6 months old, and that ls will print the year instead of the exact time. For files newer than 6 months old, you'll just have ...


0

find dir -name just supports shell file name glob characters as documented by man fnmatch. Some find implementations support non-standard extensions for regular expressions. Check your find man page.


1

-name takes wildcard patterns, not regexps and matches on the file name, not its full path. Use -regex (or -iregex) for regexp matching but beware it matches against the full path. Here, you could do: LC_ALL=C find -E . -iregex '.*s[0-9]{1,2}\.?e[0-9]{1,2}[^/]*\.mkv' Here, we're replacing the second .* with [^/]*, that is a sequence of non-/ characters to ...


1

You have misunderstood how hard links work. There is no original. All files are simply hardlinks to an inode. Therefore, hardlinks don't actually link to files, they link to inodes. To illustrate, consider this file: $ touch file $ ls -li file 3282140 -rw-r--r-- 1 terdon terdon 0 May 3 16:27 file As you can see above, file points to the inode 3282140. ...


4

I am not sure what your intention is (you didn't make that clear), but if it's to chmod to 700 all the files that match the pattern, then, except for your typo (;\ instead of \;), your command seems to work as intended. However: when it finds a file containing that string grep -q gives me 0 so another exec executes but should not. Yes, it should do. 0 ...


11

GNU find has an optimization which can be applied to find . but not to find . -type f: if it knows that none of the remaining entries in a directory are directories, then it doesn't bother to determine the file type (with the stat system call) unless one of the search criteria requires it. Calling stat can take measurable time since the information is ...


2

You can pipe your find into a sort that sorts primarily by the number of / characters in the pathname. For example, find alpha | awk '{n=gsub("/","/",$0);printf "%04d/%s\n",n,$0}' | sort -t/ | sed 's|[^/]*/||' This uses awk to prefix the pathname with the number of slashes, and sed to remove this prefix at the end. Actually, as you probably want the ...


4

You can do it with just shell wildcards. Build up a pattern with progressively more directory levels. pattern='*' set -- $pattern while [ $# -ne 1 ] || [ "$1" != "$pattern" ]; do for file; do … done pattern="$pattern/*" set -- $pattern done This misses dot files. Use FIGNORE='.?(.)' in ksh, shopt -s dotglob in bash, or setopt glob_dots in zsh ...


2

Given a path to the file ./some/where/thatcertainfile, stripping off the final /thatcertainfile gives you a path to the directory. Launch a shell to be able to use string manipulation on the path. find . -name thatcertainfile -exec sh -c 'rm -r "${0%/*}"' {} \; Alternatively, use zsh. To transform a path into the name of the containing directory, use the ...


0

Try this command: rm -rf $(find . -name thatcertainfile -execdir pwd \;) It should say to the rm -rf that what it had to remove is the output of your command. For example, if your command's output was /home/guest/Documents the command I showed would translate on rm -rf /home/guest/Documents.


0

Use sed for file in */*.ext; do ext2=`echo $file | sed 's/.ext/.ext2/'` mv $file $ext2 done


1

You can use the -printf function of find to construct your commands: find /tmp -name "*.ext" -printf "mv %p %h/new_name.ext" mv /tmp/foo.ext /tmp/new_name.ext When you surround the command with $(), the commands will be executed: $(find /tmp -name "*.ext" -printf "mv %p %h/new_name.ext") find /tmp -name "*.ext" /tmp/new_name.ext Update: The above ...


0

find is not a simple command that is controlled by options but a command that implements an own control language. The find CLI looks like: find [options] path1..pathn [expression] Where options are e.g. -H, -L, -P and expression is a script written in the find control language. The parameters like -name are called: primaries, because they are primary ...


5

This "return" isn't the exit code of find, but the return value of the -execdir action for the purposes of chaining multiple find actions together. If you try: find . -execdir false '{}' \; -print then -print never executes (that is, there is no output), while both of: find . -execdir true '{}' \; -print find . -execdir false '{}' + -print print every ...


2

find and cpio were created by Dick Haight and not by the people who wrote most of the orginal Unix utilities. There was no commandline argument parsing library at the time that you could link as a library, and that would enforce/stimulate some consistency (in the mid 80s I had source code for getopt on several systems ) Once people use commands and their ...


2

You seem to have confused a few things. Neither find nor cp are shell builtins. The only argument in the find command is the path, the rest are options and their values, but that's just semantics, the distinction here is not very important. More importantly, there are two classes of option flags. Those that take arguments and those that don't. For those that ...


4

The commands came first, consistency was added later. The earliest manpage you're likely to find shows it as find pathname expression find dates back to the 1970s, and the assumptions of ordering and even syntax (whether a dash is needed for options) were added to various commands later (say during the later 1980s and early 1990s) to help users remember ...


0

Modern find (via POSIX, so the not-GNU find on OpenBSD does support this) can do the necessary work without a call to xargs via the -exec command {} + form. find ... -exec rm -rf '{}' \+


3

If you're using -print0 you should use the -0 flag to xargs so it will read the names correctly. find ~/.jenkins/jobs/subco/workspace/myproject/ -name 'target' -print0 | xargs -0 rm -rf alternately, if you have GNU find you could use the -delete flag, though it won't work if the directories are not empty find ~/.jenkins/jobs/subco/workspace/myproject/ ...


0

I've see this happen on Mac when the directory is on removable media which has been removed and readded since the terminal window was opened. I can't explain why (probably has to do with information cached when the terminal session was started), but it was reproducible. Just restarted the terminal session and all was fine.


3

LC_ALL=C find . ! -name '*.gz' \ -type f \ -size +"$((500*1024*1024))c" \ -mtime +0 \ -exec gzip {} + Here using gzip for compression. See also xz, bzip2 or compress for other compression utilities with different compression formats. Note that some find implementations like GNU find also ...


2

If you don't want to descend into any of the directories named @eaDir then you should not use ! before -name: mkdir -p a/@eaDir mkdir -p b/c/@eaDir mkdir -p d/e/f touch a/@eaDir/xxx touch b/yyy touch b/c/@eaDir/xxx touch d/e/f/yyy find . -name '@eaDir' -prune -o -print will give you: . ./b ./b/yyy ./b/c ./a ./d ./d/e ./d/e/f ./d/e/f/yyy and ...


3

Defining aliases or functions to simplify commands you use often is the standard way. I don't know of any built-in function or command to do this same thing, provided as standard on most Linux and Unix-type systems. There are undoubtedly similar aliases or functions in pre-packaged collections; for example, Oh My Zsh's common-aliases plugin defines fd and ff ...


0

Here's my take on it, incorporating ideas from @ArionKrause and @don_crissti: #!/bin/bash # adapted from http://unix.stackexchange.com/a/157594/110635 # and http://unix.stackexchange.com/a/220619/110635 W=1024 H=768 SIZE_TEST="%[fx:(h>$H && w>$W)]"'\n' for f in $*; do if [ $(identify -format "$SIZE_TEST" "$f") == 1 ]; then echo "Resize: ...


1

Following up on @cas's comment to another answer: six_months=$(date -d "6 months ago" "+%Y%m%d") for f in *.Txt; do file_date=${f%.Txt} [[ $file_date > $six_months ]] && echo "$f" done | xargs awk 'FNR > 1 {print $3}' | sort -u > unique_ids_in_last_6_months The for loop prints out the "eligible" filenames. xargs passes the ...


1

Use awk to do the work, and SQLite for the dates. sqlite3 <<< "select date('2016-04-20', '-6 month');" 2015-10-20 Dandy, ain't it? awk has string functions to insert/delete the hyphens SQLite needs and, yea, splits on tab delimiters. awk 'NR == 1 {next}; { IDS[$3]++ }; END {for (K in IDS) {print K}}' ids 123456 345678 234567 Guaranteed ...


2

Your attempts aren't working because you're trying to use shell operators such as && and > in the command executed by find, but you're typing those operators directly in the command, so they're executed by the shell that's calling find. Your commands are parsed as find … > tmp.$$ && mv … e.g. the first find invocation is find ./ ...


4

That is because you are trying to use the GNU find, which is default in Linux, but Mac OS X comes with BSD find which has many differences. To install GNU find you will need Homebrew, pretty easy to install, just follow http://brew.sh/ After that you can install findutils: brew install findutils More info and other tools to mimic a Linux environment on ...


2

It is not trivial to find the exact date 6 months ago, especially if the current date would be the 31st of some month. But if you know how to do this with find and -mtime, I would just touch the files depending on the date in their name: for x in *.Txt; do dd=${x%.Txt} touch -t "$dd"0000 "$x" done and then use the mtime


1

bash version (not POSIX compliant) #!/bin/bash find . -type d -name 'a *' -print0 \ | while IFS= read -r -d '' dir ; do find "$dir" -type f -name "*.c" -exec echo \{\} \; done Problems: read has no -d parameter in POSIX find has no -print0 parameter in POSIX (bad) sh version (POSIX compliant) #!/bin/sh # WARNING: while this will ...


1

The problem What are you trying to do? Let me try to explain your command so I understand it: ls -Ra | grep -cve/ -e'^\.*$' will give you: The number of files, directories, symbolic links, ... Including the current directory Excluding files with names only consisting of dots: touch '...' (!!!) The solution If you want to do the exactly the same with ...


0

The difference is that if you use -name you only match against the basename of the file. From man find: -name pattern Base of file name (the path with the leading directories removed) matches shell pattern pattern. The metacharacters (`*', `?', and `[]') match a `.' at the start of the base name (this is a change in ...


3

In case you want to understand the original command, let's go though that step by step. find -not -empty -type f Find all non-empty files in the current directory or any of its subdirectories. -printf "%s\n" Print its size. If you drop these arguments, it will print paths instead, breaking subsequent steps. | sort -rn Sort numerically (-n), in ...


6

You can make it shorter: find . ! -empty -type f -exec md5sum {} + | sort | uniq -w32 -dD Do md5sum of found files on the -exec action of find and then sort and do uniq to get the files having same the md5sum separated by newline.


10

You can use fdupes. From man fdupes: Searches the given path for duplicate files. Such files are found by comparing file sizes and MD5 signatures, followed by a byte-by-byte comparison. You can call it like fdupes -r /path/to/dup/directory and it will print out a list of dupes. Update You can give it try to fslint also. After setting up fslint, go to ...


1

Well it is a directory and (-type d) so it gets printed. You can try to set the minimum depth find ./d -mindepth 1 -type d


1

You can specify the max and min subdirectory depths. find ./d -mindepth 1 -type d -exec bash -c "echo '{}'" \;



Top 50 recent answers are included