0

GNU bash, version 4.4.0
Ubuntu 16.04

I am wanting to list all the files from a directory and print them to column two while printing the size of the files in column one. example

1024 test.jpg
1024 test.js
1024 test.css
1024 test.html  

I have already done so using the ls command but shellcheck is not liking it. Example:

In run.sh line 47:
ls "$localFiles" | tail -n +3 | awk '{ print $5,$9}' > "${tmp_input3}"
^-- SC2012: Use find instead of ls to better handle non-alphanumeric filenames.  

When I use the find command, it also returns the absolute path. Example:

root@me ~ # mkdir -p /home/remove/test/directory
root@me ~ # cd /home/remove/test/directory && truncate -s 1k test.css test.js test.jpg test.html && cd
root@me ~ # find /home/remove/test/directory -type f -exec ls -ld {} \; | awk '{ print $5, $9 }'
1024 /home/remove/test/directory/test.jpg
1024 /home/remove/test/directory/test.js
1024 /home/remove/test/directory/test.css
1024 /home/remove/test/directory/test.html  

What's the most efficient way to accomplish my goal. It can be any command, as long as shellcheck is cool with it, I'm happy.

Vituvo
  • 1,008
  • 1
  • 9
  • 29

3 Answers3

3

Please try:

find dir -maxdepth 1 -type f -printf "%s %f\n"
tshiono
  • 21,248
  • 2
  • 14
  • 22
1

You can use something as shown below,

This is the basic command,

vagrant@ubuntu-bionic:~$ find ansible_scripts/ -follow -type f  -exec wc -c {} \;

Output,

vagrant@ubuntu-bionic:~$ find ansible_scripts/ -follow -type f  -exec wc -c {} \;
59 ansible_scripts/hosts
59 ansible_scripts/main.yml
266 ansible_scripts/roles/role1/tasks/main.yml
30 ansible_scripts/roles/role1/tasks/vars/var3.yaml
4 ansible_scripts/roles/role1/tasks/vars/var2.yaml
37 ansible_scripts/roles/role1/tasks/vars/var1.yaml

The above command is used to depict the absolute path I get using the find command.

Below is the updated command which you can use to get only size and file name, but it may generate some ambiguity if file names are same.

Command

find ansible_scripts/ -follow -type f  -exec wc -c {}  \; | awk -F' ' '{n=split($0,a,"/"); print $1" "a[n]}'

Output

vagrant@ubuntu-bionic:~$ find ansible_scripts/ -follow -type f  -exec wc -c {}  \; | awk -F' ' '{n=split($0,a,"/"); print $1" "a[n]}'
59 hosts
59 main.yml
266 main.yml
30 var3.yaml
4 var2.yaml
37 var1.yaml

Shell check status Online Shell Check status

Shubham Vaishnav
  • 1,637
  • 6
  • 18
1

The real challenge (which shellcheck is highlighting) is the handling of filenames with embedded white spaces. Since (older versions of) ls are using newlines to separate output for different files, it's hard to process files with embedded (or trailing) newline(s).

From the question and the sample output, it not clear how files with newlines are going to be handled.

Assuming there is no need to handle file names with embedded newlines, you can use the 'wc' (with the -c).

(cd "$pathToDir" && wc -c *)

It's worthwhile to note that (newer versions) of ls provide multiple options for handling filenames with embedded newlines (e.g. -b). Unfortunately, shellcheck doesn't recognize and produces the same error message ('use find instead ...') even when the code correctly handles this situation.

To get support for the files with embedded newlines, one can leverage the ls quoting:

#! /bin/bash
     # Function will 'hide' the error message.
function myls {
        cd "$1" || return
        ls --b l "$@"
}

     # Short awk script to combine $9, $10, $11, ... into file name
     # Correctly handle file name contain spaces
(myls "$pathToDir") |
    awk '{ N=$9 ; for (i=10 ; i<=NF ; i++) N=N + " " $i ; print $5, N }'
Vituvo
  • 1,008
  • 1
  • 9
  • 29
dash-o
  • 13,723
  • 1
  • 10
  • 37
  • Spellcheck? You did mean shellcheck right? I just want to doublecheck to be sure we are on the right page. – Vituvo Sep 28 '19 at 18:13