bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [Non-DoD Source] Re: Please advise work around or bug fix


From: Yuen, Kam-Kuen CIV USARMY DEVCOM SC (USA)
Subject: RE: [Non-DoD Source] Re: Please advise work around or bug fix
Date: Thu, 25 Mar 2021 11:52:31 +0000

Hi Bob,

Thanks for the awesome explanation. I have not tested all your solutions yet. 
Will experiment it.
 But I try the following and has the attached sample output.
   
 find . -size +1k -ls

Q) Where can I find the columns heading? The standard ls command does not have 
the first two columns data.
Is there a good documentation that I can use as reference guide?

Thanks,
Kam
US ARMY, CCDC
Armaments Software Engineering Center
B31 Third Ave
Picatinny, NJ 07806
Office: 973.724.8856

-----Original Message-----
From: Bob Proulx <bob@proulx.com> 
Sent: Thursday, March 25, 2021 1:43 AM
To: Yuen, Kam-Kuen CIV USARMY DEVCOM SC (USA) <kamkuen.yuen.civ@mail.mil>
Cc: bug-findutils@gnu.org
Subject: [Non-DoD Source] Re: Please advise work around or bug fix

Yuen, Kam-Kuen CIV USARMY DEVCOM SC (USA) via Bug reports for the GNU find 
utilities wrote:
> I am running the following command and the "ls" command gives error 
> message that the file cannot be found.  The problem is that the 
> filename has spaces as part of the filename.

In addition to everything Berny said (which was quite a bit!) let me say that 
handling spaces in file names has caused a shift in thinking about how command 
lines are constructed.  Your example is a very traditional Unix example that 
works very good when the files do not have whitespace.  But as you have found 
when they do have whitespace then the model does not work.

But there are other ways that handle whitespace okay.

> The purpose is to find all files that exceeding file size of 1k.
> Filename might include spaces, special character like '
> 
> find . -size +1k -print | xargs ls -sd

Instead of using -print | xargs one can now use find only.  For example did you 
know that find has a built-in -ls option?  The -ls action in find is like "ls 
-dils".

    find . -size +1k -ls

In conjuction with other utilities and filters that may be enough to solve your 
problem completely.  But if not then there are still other ways too.

> 3)      When running "ls" command directly on the folder, the screen
> show  " ' " character surrounding the filename e.g. 'This is a Test 
> Case With spaces in Filename.pdf'
>
> 4)      In the case the filename already has ' special character,
> the "ls" command shows the filename with double " around the filename 
> e.g. " This is a Tester's File.pdf"

This quoting is due to the new incompatible quoting that the GNU ls (and GNU 
stat) commands now produce.  I do not approve but they now produce that type of 
quoted output.  I personally use the "ls -N"
option (by setting export QUOTING_STYLE="literal" in my .bashrc file) so as to 
get the traditional behavior.

> 6)      Trying to use the -0 option with xargs but it complains the argument 
> line too long

Did you use xargs -0 with find's -print0?  This should work.

    find . -size +1k -print0 | xargs -r0 ls -1sd

> Can you advise How to handle filename with hidden character like '
> or space or to report file size of current and subdirectories

If the find -ls action is not sufficient:

    find . -size +1k -ls

Then I would use this following technique since it effectively exactly answers 
the question you asked.  Try this:

    find . -size +1k -exec sh -c 'ls -1sd "$@"' sh {} +

This technique is described in the find manual but it is a little subtle 
therefore I will try to explain it.

The -exec ... {} + part gathers up all of the arguments that will fit into the 
command line and passes them to the command being executed all at once.  That 
makes it very efficient.  Since find is a C program and the arguments are being 
passed internal to the program then there is no worry about splitty on 
whitespace.

The command being run in ``-exec sh -c 'ls -1sd "$@"' sh {} +'' is the ``sh -c 
'ls -1sd "$@"' sh'' command and all of the file names are arguments.  For 
example if there are three files it might be this.

    sh -c 'ls -1sd "$@"' sh file1 file2 file3

The ``sh -c'' part reads the commands from the command string which is the 
first option argument.  When using the -c option then a command name is a 
required next argument to set the command name.  The command name will be 
displayed in a process listing using 'ps'.  Most importantly though if the 
command name is not provided then the first filename provide by find will be 
used as the command name and that file will be missing!  In the above the 
second "sh" is the command name.

    man sh

     sh -c [-aCefnuvxIimqVEbp] [+aCefnuvxIimqVEbp] [-o option_name] [+o 
option_name] command_string [command_name [argument ...]]

           -c               Read commands from the command_string operand
                            instead of from the standard input.  Special
                            parameter 0 will be set from the command_name
                            operand and the positional parameters ($1, $2,
                            etc.)  set from the remaining argument operands.

Note that in the synopsis above that if the command_string includes arguments 
that a command_name must appear between them.  Let's explore that with a couple 
of examples to show this in practice.

    $ sh -c 'echo args "$@"' one two three
    args two three

    $ sh -c 'echo args "$@"' sh one two three
    args one two three

Additionally I am adding the ls -1 option to always write only one column of 
output.  Otherwise the result might be multiple columns and if the file list is 
large enough some might be multiple columns and some might not be due to the 
group of file name arguments and multiple invocations of the command.  
Therefore using ls -1 ensures that the output is always consistely 1 column.

And with those pieces and that technique we end up with the following.

    find . -size +1k -exec sh -c 'ls -1sd "$@"' sh {} +

Which I think exactly answers your question.  But the technique is very useful 
and general purpose.

Note that I thought Berny's suggestion of using du was actually the superior 
solution. :-)

    du -at +1k

Bob

Attachment: test.out
Description: test.out


reply via email to

[Prev in Thread] Current Thread [Next in Thread]