1

I've been experimenting with the file command and I came across something intriguing. When I try to loop all the files of a folder and call the file command the output for .swap and .swp files exhibit a weird behaviour. All 3-letter file/folder names in the current folder are printed as valid extensions for the swap file.

file --extension .test.swp outputs .test.swp: ??? but calling it in a loop has a different output. the difference can be seen below. This seems to happen only if

  • There is a for loop
  • file --extension is used
  • There is a .swp/.swap file which is not empty
  • There are files/folders with exactly three characters.
touch a.txt b c def 123 456
for file in `find . -type f`; do 
    echo $file "->" `file --extension $file` ; 
done
echo "test" > .test.swp
echo "-------------"
for file in `find . -type f`; do 
    echo $file "->" `file --extension $file` ; 
done

This prints the output before and after the swap file is added.

./def -> ./def: ERROR: (null)
./a.txt -> ./a.txt: ERROR: (null)
./456 -> ./456: ERROR: (null)
./123 -> ./123: ERROR: (null)
./c -> ./c: ERROR: (null)
./b -> ./b: ERROR: (null)
-------------
./def -> ./def: ERROR: (null)
./.test.swp -> ./.test.swp: 123 456 def
./a.txt -> ./a.txt: ERROR: (null)
./456 -> ./456: ERROR: (null)
./123 -> ./123: ERROR: (null)
./c -> ./c: ERROR: (null)
./b -> ./b: ERROR: (null)

Can anyone explain this weird behaviour?

EDIT: My Shell is GNU bash, version 3.2.57

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Seems to happen for .sh files too. – BlackPearl Apr 30 '19 at 17:03
  • I can't find the `--extension` option in any of the man pages I've checked. – Barmar Apr 30 '19 at 17:05
  • `file` is not part of bash. It's more important that you tell us what version of `file` you have than what version of bash you have. – Charles Duffy Apr 30 '19 at 17:09
  • That said, any `*` in the output will be munged (replaced with a list of filenames in the local directory) by the inadequate quoting. **ALWAYS** quote your expansions in shell. – Charles Duffy Apr 30 '19 at 17:10
  • @Barmar I can find this in my man page `--extension Print a slash-separated list of valid extensions for the file type found.` `file --version` gives me `file-5.33` @BlackPearl Yes. –  Apr 30 '19 at 17:10
  • That is: `echo "$file => $(file --extension "$file")"` is much less error-prone. – Charles Duffy Apr 30 '19 at 17:10
  • (`for file in $(find . -type f)` and its backtick-using equivalent is also described in [BashPitfalls #1](http://mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29) and [DontReadLinesWithFor](https://mywiki.wooledge.org/DontReadLinesWithFor) -- not that it's necessarily directly linked to the immediate behavior, but it's a source of unreliability even so). – Charles Duffy Apr 30 '19 at 17:12
  • @CharlesDuffy True. I was just curious as to what might have caused the error. I couldn't encounter `*` anywhere and became much more curious by just the 3-letter extensions. File names with any number of characters other than 3 were not printed. Seemed to be a very interesting problem. :) –  Apr 30 '19 at 17:13
  • ...whereas I'm going to argue that I called it correctly. Sure, it wasn't a `*`, but it was still an unintended glob expansion caused by inadequate quoting. – Charles Duffy Apr 30 '19 at 17:17
  • @CharlesDuffy Agreed, you did call it correctly. Wasn't expecting the '???' to mess up. –  Apr 30 '19 at 17:31

1 Answers1

3

The reason is that you didn't quote

`file --extension $file`

It's returning ??? for .test.swp, which is then being processed as a filename wildcard. So your output is the same as if you'd written

echo $file "->" ???

The wildcard ??? matches all 3-character filenames, so those are shown.

Change to:

echo "$file -> `file --extension $file`"

You should always quote variables and command substitutions unless you have a good reason not to. See I just assigned a variable, but echo $variable shows something else (it talks about variables, but command substitution works the same way).

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Wow. I overlooked that the '?' can be used as wild cards. Are there any tips to actually debug these kinds of issues? I tired using 'sh -x' flag, but it didn't reveal much. –  Apr 30 '19 at 17:25
  • 2
    @JonSnow, http://shellcheck.net/ (whether using the online or locally-installed versions) will flag this and other unquoted expansions as [SC2046](https://github.com/koalaman/shellcheck/wiki/SC2046). – Charles Duffy Apr 30 '19 at 18:08
  • @CharlesDuffy Yes, it does. Thank you. –  Apr 30 '19 at 18:10