1
iphone=($( find /  -name "*~iphone*" ) )
echo ${#iphone[@]}
rm -r ${iphone[@]} >/dev/null 2>&1

This is a portion of a script I have that should remove all files with "~iphone" anywhere in the name, as well as echoing the amount of files it found. So how might this script be modified to allow file names with spaces, as right now it messes with the count and doesn't delet the files.

  • What you need a regex to match a space, which can be passed instead of "*~iphone". check this link http://stackoverflow.com/questions/18514135/bash-regular-expression-cant-seem-to-match-s-s-etc ..might help. – Kislay Kishore Jan 30 '16 at 07:39
  • Another link with little extra details : http://unix.stackexchange.com/questions/251674/any-non-whitespace-regular-expression – Kislay Kishore Jan 30 '16 at 07:45
  • Possible duplicate of [How can I store find command result as arrays in Bash](http://stackoverflow.com/questions/23356779/how-can-i-store-find-command-result-as-arrays-in-bash) – Jahid Jan 30 '16 at 10:13
  • `find / -name "*~iphone*" -print -exec rm -r {} \; > files_found.txt`? To count files found `wc -l files_found.txt` – nsilent22 Jan 30 '16 at 10:35
  • 1
    If you are using `bash` 4, skip `find` and use `iphone=( /**/*~iphone* )` after setting the `globstar` option. – chepner Jan 30 '16 at 14:20

1 Answers1

1

One quick way to handle this would be with process substitution. (note: the remove rm is commented until you confirm desired behavior)

#!/bin/bash

while read -r fname; do
    echo "$fname"
    # rm -r "$fname" >/dev/null 2>&1
done < <(find / -name "*~iphone")

This would find all files/directories containing "*~iphone" regardless of spaces and allow deletion. If you want to build an array allowing spaces in the filename, just add "$fname" to the array each time through the loop.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 1
    better use `-print0` with find. [see this answer](http://stackoverflow.com/a/23357277/3744681) – Jahid Jan 30 '16 at 10:40
  • As @Jahid suggested : A `-print0` will allow you to handle files with both spaces and new-lines, though `read` should be `read -rd ''`. – Rany Albeg Wein Jan 30 '16 at 11:37
  • @Jahid while you would use `-print0` if piping the results to a second process (e.g. `xargs`), as used above `-print0` would result in `$fname` containing a string of filenames, instead of discrete filenames, one-per-line. – David C. Rankin Jan 30 '16 at 16:43
  • I am not talking about piping the result to a second process or using xargs. This is what I am talking about: `while IFS= read -r -d $'\0'; do echo "$REPLY" done < <(find / -name "*~iphone" -print0)` I gave a link to this answer in my previous comment – Jahid Jan 30 '16 at 17:00
  • I know what you have suggested, what I'm saying is it is absolutely unnecessary in this situation. Yes, you can do it that way, but why? The process substitution as is, provides `'\n'` delimited filenames, one-per-line, spaces are irrelevant. Try it both ways. (yes, I understand you can protect against filenames that contain `newlines` as part of their names -- in that case, your correct, there are always cases that can be imagined -- so yes, if you are one of those that creates filenames with embedded `'\n'` (or other control chars) or are on an OS that does it for you, then `-print0`.) – David C. Rankin Jan 30 '16 at 17:44