Tag Info

Hot answers tagged

7

A -exec needs to be terminated with a ; or a +. The ; causes the command to execute once per found filename, whereas + causes the command to be executed once for all filenames. Here is a working example: find ! -iname "*.JPG" -exec dirname {} \; Some notable differences from your attempts: There must be a space between {} and \; The ; must be escaped, ...


6

With GNU awk 4.1 or above: find . -type f -exec awk ' @load "inplace" BEGINFILE { inplace_begin(FILENAME, "") print "line1\nline2" } {print} ENDFILE { print "line3\nline4" inplace_end(FILENAME, "") }' {} +


5

With GNU find: find . -name foo.mp4 -printf '%h\n' With other finds, provided directory names don't contain newline characters: find . -name foo.mp4 | sed 's|/[^/]*$||' Or: find . -name foo.mp4 -exec dirname {} \; though that means running one dirname command per file. If you need to run a command on that path, you can do (standard syntax): ...


4

Whatever you do, you'll need to invoke a shell to perform the redirection of the command output to a file whose location depends on the find result. find ./ *.md -not -path './/.git/*' -exec sh -c 'COMMAND "$0" > ~/wiki/newdirectory/"${0##*/}.cong"' {} \; Don't substitute {} inside the shell script. This isn't supported on all systems, and even where ...


4

The rationale given in the POSIX specification is: The "-exec ... {} +" syntax adopted was a result of IEEE PASC Interpretation 1003.2 #210. It should be noted that this is an incompatible change to the ISO/IEC 9899:1999 standard. For example, the following command prints all files with a '-' after their name if they are regular files, and a '+' ...


4

Did you have a /Downloads folder before? Because most likely, now your Blah directory is /Downloads. In the future, you probably should avoid using sudo for these types of operations. They're all inside your own directory, you shouldn't need to use it at all.


4

Since your primary aim is to have a combined view of your local and external Music folder, I think a union mount via overlayfs could be used, especially if the files are not being written to. The basic command is, in older kernel versions (<3.18): mount -t overlayfs -o lowerdir=/read/only/directory,upperdir=/writeable/directory overlayfs /mount/point ...


3

man rsync says about --files-from: The filenames that are read from the FILE are all relative to the source dir -- any leading slashes are removed and no ".." references are allowed to go higher than the source dir. So try making the paths output by find relative: rsync -avz ... --files-from=<(ssh user@remote1 'cd /home/admin/Backup/; ...


3

Something along the lines of: find . -print -exec file {} \; | grep "PalmOS" To tidy up the output pipe through awk as well by adding: | awk '{print substr($1,2,length($1)-2)}'


3

In the first instance, * is expanded by the shell before it gets to rename (if it is expanded at all - I doubt anything matches {}/*), and if it isn't expanded, the command that is executed is rename with the three arguments -n, s/jpg/jpeg/ and some/path/*. That last argument is not the name of an existing file so rename does nothing. Without shell ...


3

Although it's not exactly the same thing as piping to xargs ls -al, the -ls flag of find itself might be enough for your and simplify the command a bit: find . ! -user username -mtime +365 -type f -ls > /tmp/list If you think a file is missing, look at what stat says about it. Keep in mind that -mtime is a condition concerning modification time. ...


3

Try: find -type f ! -iname "*.JPG" -exec dirname {} \; | sort -u Notes; To complete the -exec command, a {} is needed to show where the filename should go and a semicolon is needed. Because the shell would eat a plain semicolon, we have to escape it so that it is passed on to find. -iname matches globs, not regular expressions. So, the final $ in ...


3

find -type f -name "*-thumb.png" -exec rm {} \; If you need a prompt to confirm deletion, use -ok in place of -exec as: find -type f -name "*-thumb.png" -ok rm {} \;


3

The syntax: -exec [command] ... {} ... ; -exec [command] ... {} ... + Since ; is part of shell syntax, you need to escape it so that find sees it as an argument: find .. -exec dirname {} \; By the way, -iname doesn't use regular expressions - just use *.jpg without the $. It strikes me now that with GNU find we don't need to use dirname at all. ...


3

You don't need xargs at all, just use exec option: find . -maxdepth 1 -name "*.md" -exec aspell check {} \; And just in case you, or any future reader, will really need to use xargs - you can do that by spawning new shell and taking standard input from terminal (/dev/tty): find . -maxdepth 1 -name "*.sh" | xargs -n1 sh -c 'aspell check "$@" < ...


2

If you want to use shell parameter expansion then run some shell with exec: find . -type f -exec sh -c 'echo "${0##*.}"' {} \;


2

With zsh on a GNU system with uconv and recode: { echo '<html><head><meta charset="UTF-8"</head><body><pre>' users=(/var/cpanel/users/*(:t)) && find /home/$^users/public_html -type f -ctime -1 ! -iname '*cache*' -ls | uconv --from-callback escape-c -f utf8 -t utf8 | recode u8..html echo ...


2

Try: cd /var/cpanel/users && for i in * do find "/home/$i/public_html" -type f ! -iname '*cache*' -ctime -1 -ls done > /home/demo4/public_html/output.html Notes: Use >> instead of >, otherwise each iteration overwrites the output of the last. Or redirect the output of the whole loop, in which case you can use >. some find ...


2

{ touch /tmp/sleep.flag; sleep 2d ; rm /tmp/sleep.flag; find /home/disk1/ -exec touch {} \; ; } & Everything what you need just check /tmp/sleep.flag file existance [ -f /tmp/sleep.flag ] && echo "Running sleep..."


2

You can also use gnu stow, a symlink farm manager. Assume the following layout: . ├── drive │   ├── a │   │   ├── b │   │   │   └── bar │   │   └── c │   │   └── baz │   └── b └── music └── a └── b └── foo Execute: $ stow --target music --dir drive . Result: . ├── drive │   ├── a │   │   ├── b │   │   │   └── bar │   │   └── ...


2

Try: $ find -type d -name '*dir*' -exec sh -c ' for d do for f in "$d"/*; do [ -f "$f" ] && mv -- "$f" /path/to/test done done ' sh {} +


2

mv "$dir_path"/* ... will not only move files but everything in "$dir_path". At least everything whose name does not start with a dot (hidden files). In bash you can change this with the option dotglob. But if the * expands nicely (matches everything but not too much for a command line) then you can use a shell for indirection: find . -type d -name "*dir*" ...


2

Decision1: Use GNU sed instead of awk sed -i -e '1 i\line1\nline2' -e '$ a\line3\nline4' ./* Decision2: Use loop for for each file in directory for file in ./* do awk ' BEGIN { print "line1\nline2" } { print $0 } END { print "line3\nline4" } ' "$file" > "$file".tmp && mv -f "$file".tmp "$file" done


1

Try using ps to look for the sleep command: { sleep 20; find ...; } & parent=$! if ps --ppid $parent | grep sleep then echo Sleep is running fi


1

find . -type f | while read file; do echo "${file##*.}"; done Has the advantage of bypassing all that tricky exec syntax that no one can ever remember. Also has the advantage of only creating one child process, instead of creating and destroying one for every found file. This is considerably faster than jimmij's version using exec # Preparation - 1000 ...


1

If your find accepts -execdir, this should work find . -name '*.md' -not -path './/.git/*' -execdir COMMAND {} > ~/wiki/newdirectory/{}.cong \; Alternately find . -name '*.md' -not -path './/.git/*' -exec bash -c \ 'for f; do COMMAND "$f" > ~/wiki/newdirectory/"${f##*/}".cong; done' _ {} +


1

Before answering your answer, I highly recommend you reading two question: Why does my shell script choke on whitespace or other special characters? Security implications of forgetting to quote a variable in bash/POSIX shells For your question, you don't need a for loop, just find itself: find -type d If you want to do more things, just use -exec ...


1

If you're really just looking to echo the results of find, you can use the parameter -print (or just no additional parameter at all) to have find print a list of its results. If you want to delete the results, there's -delete (which can be combined with -print to get a list of the deleted files). If you want to do something else with/to the results, you ...


1

Something like the following works ... find . -type d | while read dir; do echo $dir; done . ./my dir Depending on what you're doing, you might be better using find's -print0 option and xargs -0. The code you've got takes the unquoted output from find and uses it as a list of words (split on whitespace) for for to iterate over.


1

Do not use for loop, use while instead: find . -type d -print0 | while read -d '' -r dir; do echo "$dir"; done Option print0 prints NULL character at the end of file/directory name (instead of newline) and read -d '' interprets it properly.



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