0

Can anyone explain why the command below produces the following error:

cannot open `{}' (No such file or directory)

Command

$ ls -al|grep -v '^d\|^$'|awk '{print $10}'|xargs file '{}'

I get the results I expected but with an error

{}:          cannot open `{}' (No such file or directory)
cpuinfo:     empty
cygdrive:    symbolic link to /cygdrive
devices:     empty
filesystems: empty
loadavg:     empty
meminfo:     empty
misc:        empty
mounts:      symbolic link to self/mounts
partitions:  empty
self:        symbolic link to 19812
stat:        empty
swaps:       empty
uptime:      empty
version:     empty
jes516
  • 813
  • Because you didn't tell xargs to use {} as the replace-str? xargs -I {} .... BTW what are you trying to do, exactly? Parsing the output of ls -al isn't very robust – steeldriver Jul 08 '16 at 14:01
  • for xarg, the {} construct is unnecessary. If you drop it, your command might work, if the rest of it is sound. find ./ -type f | xargs file is a better suited command to what I think it is that you are trying to do, in my opinion – MelBurslan Jul 08 '16 at 14:01
  • Because column 10 is null/blank somewhere in you awk output. – ankidaemon Jul 08 '16 at 14:02
  • @ankidaemon.. yes you are right. I think he is trying to extract the regular file names, which usually is the 9th field in ls -al output, unless his ls command is aliased to something that inserts an additional field – MelBurslan Jul 08 '16 at 14:04
  • 1
    @MelBurslan: yes, and parsing of ls -al always have unexpected behavior. we can't we sure at which column file-name/dir-name is. He should be using find instead. – ankidaemon Jul 08 '16 at 14:09
  • @ankidaemon yes, i am extracting the file names. i dont recall which field the file name is in ls when using linux but this is on cygwin (possible reason for difference). basically i would like to pass a list of filenames to file command ie. file filename1 filename2 filename2 – jes516 Jul 08 '16 at 14:37
  • 1
    find . -maxdepth 1 -type f -exec file {} + seems to work for me in Cygwin64 – steeldriver Jul 08 '16 at 14:40
  • i believe the problem is with ls -al as the first line from that command is total 4 when that line with total is being passed to awk, it prints an empty line since there is no field 10. sorry, im still not as fluid with bash/linux as i would like to be and i can overthink things – jes516 Jul 08 '16 at 14:45
  • Don't Parse ls - @steeldriver's find method is much better, starting with the fact that it actually works. BTW, $10from ls -al isn't guaranteed to contain even part of the filename, let alone all of it. – cas Jul 09 '16 at 13:32
  • @cas 'ls' isnt guaranteed to have the full file name because of spaces? – jes516 Jul 09 '16 at 15:19
  • ls will output the full filename. The tenth field of its output won't necessarily have any or ALL of the filename due to spaces,tabs, control-chars incl. newlines and other annoying but perfectly valid characters. also because the number of fields in ls output can vary depending on the file's timestamp and the version of ls. Just Don't Parse ls. It's completely unreliable and there are far better, easier, and actually reliable ways. – cas Jul 09 '16 at 15:48

1 Answers1

2

Because you're using xargs wrong, you've probably been inspired by how find works.

xargs takes the input and splits it into pieces to produce few commands, but (unless you've asked it into) it gives multiple arguments at the end of the command you secify after xargs, so your {} is just a part of the command. So you end up executing file {} <file_1> <file_2> ... <file_n>, file {} <file_n+1>..., .... (In your case you have so few files that only one command is executed.)

As you don't have a file called {}, file tells you so.

  • It not about the wrong use of xargs. Splitting of ls -al output is wrong. this should not be the way to split ls -al. He is getting the error because of null/blank in output of awk. – ankidaemon Jul 08 '16 at 14:08
  • I agree that the spliting of ls -al output is wrong, but that error also occurs in a directory where everything is simple enough not to trigger the problems with the splitting (if I change $10 to $9, but that might be his ls that is aliased to something weird). – Henrik supports the community Jul 08 '16 at 14:35
  • I think it'd be worth mentioning -I, which lets you do exactly that, and is very useful if (for whatever reason) you need to put the arguments in the middle of your command. –  Jun 26 '18 at 21:30