I'd use file
and pipe the output into grep or awk to find text files, then extract just the filename portion of file
's output and pipe that into xargs.
something like:
file * | awk -F: '/ASCII text/ {print $1}' | xargs -d'\n' -r flip -u
Note that the grep searches for 'ASCII text' rather than any just 'text' - you probably don't want to mess with Rich Text documents or unicode text files etc.
You can also use find
(or whatever) to generate a list of files to examine with file
:
find /path/to/files -type f -exec file {} + | \
awk -F: '/ASCII text/ {print $1}' | xargs -d'\n' -r flip -u
The -d'\n'
argument to xargs makes xargs treat each input line as a separate argument, thus catering for filenames with spaces and other problematic characters. i.e. it's an alternative to xargs -0
when the input source doesn't or can't generate NULL-separated output (such as find
's -print0
option). According to the changelog, xargs got the -d
/--delimiter
option in Sep 2005 so should be in any non-ancient linux distro (I wasn't sure, which is why I checked - I just vaguely remembered it was a "recent" addition).
Note that a linefeed is a valid character in filenames, so this will break if any filenames have linefeeds in them. For typical unix users, this is pathologically insane, but isn't unheard of if the files originated on Mac or Windows machines.
Also note that file
is not perfect. It's very good at detecting the type of data in a file but can occasionally get confused.
I have used numerous variations of this method many times in the past with success.
I don't believe that there is any way to determine whether a filesystem is remote or local using only POSIX interfaces. POSIX doesn't even mandate a mount
command, and all references to file systems, as far as I know, are replete with the words "implementation-defined".
The -local
primary to the find
command is not much help, since it is only available on Solaris, and it depends on the existence of a configuration file which lists remote filesystem types.
POSIX does mandate a df
command and requires a specific output format if that command is used with the -P
flag; in that format, there are six space-separated fields, of which the first is the "name of the file system, in an implementation-defined format" and the last is the mount point.
What you need is a list of all the mount points corresponding to local filesystems. Here, I think you're going to have to fall back to a heuristic; which is to exclude filesystem names which "look like" remote filesystems. Some examples:
//... CIFS (Samba)
host:... NFS
/afs AFS
That's not an exhaustive list, and it comes completely without guarantees.
If you then filter those lines out of the output of df
and then remove the first five columns, you could then feed the list to the find
command with the -xdev
primary.
Even if that sounds plausible, there is actually no guarantee that a filesystem is actually "mounted" (see AFS) or that a filesystem is either entirely local or entirely remote (a fuse-based filesystem can arbitrarily redirect individual files). So proceed with caution, is my advice.
Best Answer
You can always do:
To list the files you don't have read permission for.
Note that for symlinks, that checks the target of the symlink.
It also obviously won't report files in directories you don't have read permission to (which may contain files you have read access to (provided you have search access to the directory) and/or files you don't have read access to).
On FreeBSD, you should also be able to do:
Or
To also list the files in the directories you don't have read access to.
(neither
sudo
,-print0
norperl
are specified by POSIX).