2

I have the following two files in my working directory:

test.txt and img.jpg

test.txt is a character special file

img.jpg is a block special file

Now I want to find if these files are character special files or block special files using shell script.

I have written the following two shell scripts:

First-

#! /bin/bash

echo -e "Enter file name: \c"
read file_name

if [ -c $file_name ]
then
    echo Character special file $file_name found
else
    echo Character special file $file_name not found

Input:

test.txt

Output:

Character special file test.txt not found

Second-

#! /bin/bash

echo -e "Enter file name: \c"
read file_name

if [ -b $file_name ]
then
    echo Block special file $file_name found
else
    echo Block special file $file_name not found

Input:

img.jpg

Output:

Block special file img.jpg not found

Where am I going wrong?

2 Answers 2

4

You're slightly wrong in your assumptions. Block special files are things like hard drive partition, memory devices. For instance, the main partition of my hard-drive is /dev/sda1. The test's (aka [) -b flag will work for that, but it won't work for a picture file, which is considered a regular file.

$ test -b ./Pictures/NOTEBOOKS/8.jpg && echo "It's a block device" || echo "Not  a block device"                                                                                        
Not  a block device
$ test -b /dev/sda1  && echo "It's a block device" || echo "Not  a block device"                                                                                                        
It's a block device

Character devices are things like tty and serial consoles. For instance:

$ test -c /dev/tty1 && echo "It's a character device" || echo "Not a character dev"                                          
It's a character device

And stat can tell you pretty much this same information, just in text form instead of exit status like test does:

$ stat --printf "%n\t%F\n"  /dev/tty1 /dev/sda1 ./mytext.txt ./Pictures/NOTEBOOKS/8.jpg                                      
/dev/tty1   character special file
/dev/sda1   block special file
./mytext.txt    regular file
./Pictures/NOTEBOOKS/8.jpg  regular file

What you should be doing is using file command, and checking its output:

$ file ./Pictures/NOTEBOOKS/8.jpg                                                                                                                                                       
./Pictures/NOTEBOOKS/8.jpg: JPEG image data, JFIF standard 1.02, aspect ratio, density 100x100, segment length 16, baseline, precision 8, 750x750, frames 3
$ file /dev/sda1
/dev/sda1: block special (8/1)
$ file mytext.txt
mytext.txt: ASCII text
4
  • Thanks for your answer, please view this video, youtube.com/…, I am learning shell scripting by following this online tutorial
    – Sonevol
    Jul 16, 2017 at 9:17
  • 1
    Your answer makes my understanding crystal clear. However at the same time it means that the author of the above said tutorial is completely wrong.
    – Sonevol
    Jul 16, 2017 at 9:31
  • @Sonevol I watched the video, found the part where they mention it at 7:22. Yep, the author of the video is wrong. A picture or video file is still considered regular file, it is not block file. A text file with words in it is not character file. Character file (or more commonly, character devices) read characters, so say I have Arduino or Raspberry Pi on /dev/ttyUSB0 , and if I write characters there, those devices will read what I'm sending to them. Jul 16, 2017 at 9:36
  • Actually, I'd suggest you read this: unix.stackexchange.com/a/60147/85039 Jul 16, 2017 at 9:37
3
$ cat test-c.bash 
#! /bin/bash

echo -e "Enter file name: \c"
read file_name

if [ -c $file_name ]
then
    echo Character special file $file_name found
else
    echo Character special file $file_name not found
fi
$ bash test-c.bash 
Enter file name: /dev/tty
Character special file /dev/tty found
$ cat test-b.bash
#! /bin/bash

echo -e "Enter file name: \c"
read file_name

if [ -b $file_name ]
then
    echo Block special file $file_name found
else
    echo Block special file $file_name not found
fi
$ bash test-b.bash 
Enter file name: /dev/sda
Block special file /dev/sda found

Except for the missing fi in your programs, they do what one would expect.

Your assumption...

test.txt is a character special file

img.jpg is a block special file

...probably is wrong if you have not created them to fulfil this e.g. using mknod.
(See man mknod.)

So if your test files are what the names are hinting to, they are just plain normal (regular) files.

What were you looking for?

A way to distinguish between text files and binary files like in DOSish operating systems?

This is a relict of CP/M days or even older. The filesystem did track the file sizes in blocks and therefor text files needed an end of file character to flag the end of valid text.

The consequence is, that concatenation of binary files and text files has to be done differently.

Unixish filesystems track the file's size in blocks and in actually used bytes, so there is no need to flag the text end using a special end character.

If you want to guess what's inside a file, you can use the file command:

$ file 20170130-094911-GMT.png 
20170130-094911-GMT.png: PNG image data, 744 x 418, 8-bit/color RGBA, non-interlaced
$ file calendar.txt 
calendar.txt: ASCII text

HTH!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .