Сценарий оболочки для проверки наличия специальных файлов символов и специальных файлов блоков.

Вот bash -центральная версия; он опирается на следующие функции bash:

cdd() {
  local _cdd_unset_globstar=0
  shopt -q globstar || _cdd_unset_globstar=1
  shopt -s globstar
  local _cdd_deepest=$1
  local _cdd_level=1
  local _cdd_array=()
  for d in "${1}/"**/
  do
    IFS=/ read -r -d '' -a _cdd_array <<< "$d" || true
    if [ "${#_cdd_array[*]}" -gt "$_cdd_level" ]
    then
      _cdd_deepest=$d
      _cdd_level=${#_cdd_array[*]}
    fi
  done
  cd -- "$_cdd_deepest" && true
  local _cdd_ret="$?"
  [ "$_cdd_unset_globstar" -eq 1 ] && shopt -u globstar
  return "$_cdd_ret"
}

Функция выполняет следующие действия:

  1. проверяет, не установлена ​​ли уже опция оболочки globstar; если нет, то сохраняем флаг для сброса опции в конце.
  2. инициализировать текущий -самый глубокий известный каталог и его уровни($1и 1соответственно ).
  3. Развернуть все подкаталоги с заданным параметром и просмотреть их в цикле.
  4. Для каждого подкаталога прочитать его в массив, разделенный /; подсчитайте количество элементов в массиве и сравните его с известным в настоящее время -самым глубоким уровнем каталога. Если это глубже, сбросьте эти переменные.
  5. Когда у нас есть самый глубокий подкаталог, cdв него.
  6. Если нам нужно сбросить параметр оболочки globstar, сделайте это.

Если вам кажется более правильным использовать подоболочку для установки опций оболочки, то вы можете подойти к этому с помощью двух функций :оболочки и подоболочки -, вызывающей функцию, которая делает вышеописанное:

cdd_helper() (
  shopt -s globstar
  _cdd_deepest=$1
  _cdd_level=1
  for d in "${1}/"**/
  do
    IFS=/ read -r -d '' -a _cdd_array <<< "$d" || true
    if [ "${#_cdd_array[*]}" -gt "$_cdd_level" ]
    then
      _cdd_deepest=$d
      _cdd_level=${#_cdd_array[*]}
    fi
  done
  printf "%s" "$_cdd_deepest"
)

cdd() {
  cd -- "$(cdd_helper "$1")"
}

0
16.07.2017, 07:36
2 ответа

Вы немного ошиблись в своих предположениях. Блокировать специальные файлы — это такие вещи, как раздел жесткого диска, устройства памяти. Например, основной раздел моего жесткого диска -— /dev/sda1. Тестовый флаг (или[)-bбудет работать для этого, но он не будет работать для файла изображения, который считается обычным файлом.

$ 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

Символьные устройства — это такие вещи, как tty и последовательные консоли. Например:

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

И statможет сообщить вам практически ту же информацию, только в текстовой форме вместо статуса выхода, как это делает test:

$ 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

Вам следует использовать команду fileи проверить ее вывод:

$ 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
3
28.01.2020, 02:15
$ 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

За исключением отсутствующего fiв ваших программах, они делают то, что и следовало ожидать.

Ваше предположение...

test.txt is a character special file

img.jpg is a block special file

...вероятно, это неправильно, если вы не создали их для выполнения этого, например. используя mknod.
(См. man mknod.)

Таким образом, если ваши тестовые файлы соответствуют названиям, то это просто обычные (обычные )файлы.

Что вы искали?

Способ различать текстовые файлы и двоичные файлы, как в операционных системах DOS?

Это реликт времен CP/M или даже старше. Файловая система действительно отслеживала размеры файлов в блоках, и поэтому текстовые файлы нуждались в символе конца файла, чтобы пометить конец действительного текста.

Следствием этого является то, что объединение двоичных файлов и текстовых файлов должно выполняться по-разному.

Файловые системы Unix отслеживают размер файла в блоках и в фактически используемых байтах, поэтому нет необходимости помечать конец текста с помощью специального символа окончания.

Если вы хотите угадать, что находится внутри файла, вы можете использовать команду file:

$ 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

ХТХ!

3
28.01.2020, 02:15

Теги

Похожие вопросы