Tag Info

Hot answers tagged

20

The quotes protect the contents from shell wildcard expansion. Run that command (or even simpler just echo *test.txt in a directory with a footest.txt file and then one without any files that end in test.txt and you will see the difference. $ ls a b c d e $ echo *test.txt *test.txt $ touch footest.txt $ echo *test.txt footest.txt The same thing will ...


6

Simple use: find . -size +1M -delete If you insist using xargs and rm with find, just add -print0 in your command: find . -size +1M -print0 | xargs -r0 rm -- Other way: find . -size +1M -execdir rm -- {} + From man find: -print0 True; print the full file name on the standard output, followed by a null character (instead of the newline ...


6

you can use the --attributes-only switch of cp for this purpose, eg. find . -iname "*.txt" -exec cp --attributes-only -t dummy/ {} + From the man page of cp: --attributes-only don't copy the file data, just the attributes This will create empty files with all attributes of the original file preserved but no contents.


5

Option -0 of xargs means that output from pipe is interpreted as null terminated items. In such case you also need to create input for the pipe with find ... -print0.


5

The man page for GNU find describes -execdir in part thusly: Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find. So there is no real subtlety involved. -exec invokes the command from the directory that you run find from (and thus needs to ...


4

You missing ; character to terminate primary expression (See POSIX find): find . -type f -name \*.out -exec basename {} ';' The reason you must escape, or quote ; because it's your shell list separator. You must make your shell treat it literally. \;, ';' or ";" all work well. But this solution will call basename for each file found, make it slow. If ...


4

Assuming you have the rename command installed, use: find . -name '*"*' -exec rename 's/"//g' {} + The rename command takes a Perl expression to produce the new name. s/"//g performs a global substitution of the name, replacing all the quotes with an empty string. To do it with mv you need to pipe to a shell command, so you can execute subcommands: find ...


3

By default, find includes everything in its search: directories, files, and symlinks. find "/path/to/dir" -mmin -30 -not -name ".*" -exec zip -r "testfile.zip" "{}" \+ If /path/to/dir was modified in the last 30 minutes, it will pass all the tests, and zip, since it was given the -r option, will add the directory and everything under it to the archive. ...


3

In the first case, dump* is interpreted by the shell, and expanded into matching filenames, and then passed to find. In effect, find sees: find dumpa dumpb ... -type f ... In the second case, no interpretation is done by the shell. find does the filtering. Therefore, considering the recursive nature of find, the second method can locate files which the ...


3

Your command is missing a semicolon at the end, to terminate the -exec: find . -type f -name \*.out -exec basename {} \; But that command will run quite slowly because it forks an external process and calls basename for each and every match. If your find supports the -printf option, you might want to use that instead: find . -type f -name \*.out -printf ...


3

xargs -0 -I {} mv {} {} | tr -d \" doesn't make sense: mv doesn't produce output. Thus you cannot build pipelines with mv. find . -name '*"*' -exec bash -c 'mv "$1" "${1//\"/}"' bash {} \; or with less overhead find . -name '*"*' -exec bash -c 'for file in "$@"; do mv "$file" "${file//\"/}"; done' bash {} +


3

You can use find: find /usr -name '0914_Jul-2014.gz' -exec mv {} /var/tmp \; Or for extremely nested directory hierarchies find /usr -name '0914_Jul-2014.gz' -execdir mv {} /var/tmp \; Although as the documentation states you must ensure that your $PATH environment variable does not reference the current directory (namely .) if you use -execdir


2

you left \; find . -type f -name \*.out -exec basename {} \; you add awk too: find . -type f -name \*.out -print | awk -F "/" '{print $NF}'


2

A problem can be that directory names can contain newlines, therefore the output from find should be NUL terminated. In order to have readable output pipe the result of sort through tr: find . -name "*.txt" -printf '%h\0' | sort -zu | tr '\0' '\n' Any newline in a directory name can probably be determined by looking at the next line, if it starts with ./ ...


2

POSIX compatible code which should work for any filename: find . -name '*.txt' -printf '%h\0' | tr '\0\n' '\n\0' | sort -u | tr '\0\n' '\n\0'


2

Try: find . -type f -name "*.txt" -printf '%h\n' | sort | uniq This works as follows: find . -type f -name "*.txt" -printf '%h\n' - find all files that end in *.txt and print it's directory (%h) followed by a newline. | sort - sort the directories | uniq - remove duplicates


2

Recursing into subdirectories Parsing the output of find is unreliable. What if there was a file name with a newline in it? Use find … -exec …, which guarantees reliable processing. find . -type f -exec sh -c '…' {} \; The shell snippet … receives the file name in $0. Note that this is a separate shell process, it doesn't inherit variables or functions ...


2

find(1): -newerXY reference Compares the timestamp of the current file with reference. The reference argument is normally the name of a file (and one of its timestamps is used for the comparison) but it may also be a string describing an absolute time. X and Y are placeholders for other letters, ...


2

You could convert the filename into something that can be compared directly (such as the Unix timestamp (number of seconds since the epoch), or to YYYYMMDD, which would be lexicographically sortable), and then check if it's older than six months. For example, a script like (say, at /path/to/compare.sh): #! /bin/bash LAST=$(date -d '6 months ago' +%s) for ...


2

Try this with GNU grep: grep -f Pattern.txt File.txt


2

The first directory find /var/tmp finds is /var/tmp. If you want to skip that one (and use Gnu find) then you can change the command to: find /var/tmp -depth -mindepth 1 -type d -ctime -1 -exec rm -rf {} \; or find /var/tmp -mindepth 1 -type d -ctime -1 -exec rm -rf {} \; -prune Without -depth and -prune error messages may occur because rm -rf ...


2

Use -type f if you only want regular files. If on a GNU system, the -printf predicate can show you the date. find -maxdepth 1 -type f -mtime -50 -printf "%T+ %p\n"


2

xargs reads data from stdin. When you use rm -i rm also tries to read the answer from stdin (try touch test && echo y | r -i test ; ls test) but stdin is closed by xargs (I assume) so rm reacts as if you had pressed ctrl-d at the prompt. Another solution might be find's -exec option: touch test find . -name test -exec rm -i {} \;


2

You can use getfacl tool with -Recursive option, -skipping files that only have the base ACL and pipe the output to grep. For example the following command run under /dev directory gives for me: $ getfacl -Rs . | awk -v RS= -v ORS='\n\n' '/\nuser:jimmij:rw-\n/' # file: sg1 # owner: root # group: cdrom user::rw- user:jimmij:rw- group::rw- mask::rw- ...


2

You could use find, and tell it to not descent into other filesystems (which should prevent it from accessing virtual filesystems like proc, sys, etc): find / -xdev -uid ${OLD_UID} -execdir chown ${NEW_UID} {} + This may not be as efficient. Another way to filter out the virtual files would be to remount the root filesystem somewhere else: mkdir ...


2

Without recreating the subdirectories: find . -type f -name '*.jpg' -printf /path/to/emptys/%f\\0 | xargs -0 touch


2

To have the security benefit of -execdir (which is really about making sure the command doesn't get a path with several components) and get a prompt, you can use: find . -name hello.c -okdir rm -f {} \; (note that at least the GNU implementation of find doesn't escape filenames in a way suitable for terminals as GNU rm does (wrt control, newline, ...


1

I think you do not need to rename the files. You can transform the the filenames on the fly (first sed), compare them to a date (awk) and transform the matching filenames back (second sed). find parent/directory -maxdepth 1 -type d -name 'bkp_*' | \ sed 's#parent/directory/bkp_\(..\)\(..\)\(....\)#\3\2\1#' | \ awk -v date=$(date ...


1

If you use the -prune option as suggested in this answer, the error message doesn't occur. Quoting from the above answer, Use -prune on the directories that you're going to delete anyway to tell find not to bother trying to find files in them. Testing mkdir koko cd koko touch file{1,2} cd .. find . -type d -name "koko" -prune -exec rm -rf {} \; ...


1

The problem is that find has found a directory, it matches your selection and then the command is executed. However, find wants to do what comes naturally, and that's recursing through a directory tree, but the directory it's just found has disappeared! Hence the error message. You can work around this by supplying the --depth option, which means process ...



Only top voted, non community-wiki answers of a minimum length are eligible