Разбор аргументов с вложенными операторы case

¿Cómo sé que son archivos PDF?

No lo harás a menos que lo pidas. Claro, estoy siendo pedante, pero no preguntaste sobre los archivos con .pdfen sus nombres . El hecho de que un archivo tenga los caracteres .pdfen el nombre de archivo no lo convierte en un archivo PDF .

De hecho, seamos todos -los -pedantes sobre esto :si los últimos cuatro caracteres del nombre de un archivo son .pdf, entonces siempre tendrá más de tres caracteres en su nombre .

Entonces, al hacer esto de manera incorrecta , podrías decir:

$ find. -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.pdf

¿Ves el segundo? En realidad es un ejecutable. (Lo sé, cambié el nombre. )Y también me falta un PDF que pude haber jurado estaba en el directorio de Documentos...

$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf

Entonces, usando -inamepodríamos encontrar ese, pero eso todavía está dando como resultado que no es -un -archivo PDF.

Lo que realmente queremos hacer en este caso es examinar el número mágico del archivo usando el comando file. Una opción genera el tipo MIME , que es más sencillo de analizar. La consulta findluego se convierte en un simple -name "???*".

$ find. -type f -name "???*" -print0|xargs -0 file --mime
./.bash_history:                                              text/plain; charset=us-ascii
./.bash_logout:                                               text/plain; charset=us-ascii
./.bashrc:                                                    text/plain; charset=us-ascii
./.profile:                                                   text/plain; charset=us-ascii
./Documents/McLaren 720s Coupe:Order Summary.pdf:             application/pdf; charset=binary
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF: application/pdf; charset=binary
./Documents/Setup_MagicISO.exe.pdf:                           application/x-dosexec; charset=binary
./Downloads/Setup_MagicISO.exe:                               application/x-dosexec; charset=binary
./Downloads/WindowsUpdate.diagcab:                            application/vnd.ms-cab-compressed; charset=binary

Usemos el delimitador de dos puntos y busquemos el tipo MIME application/pdf, luego pongamos a cero esa parte e imprimamos el resultado. Tomar nota,uno de mis archivos tiene dos puntos en el nombre; así que no puedo preguntarle awk a ($2==":"){print $1}.

$ find. -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF

Ahora terminemos con la idea de incluir archivos PDF llamados ayabc:

$ mkdir Documents/other
$ cp -a Documents/McLaren\ 720s\ Coupe\:Order\ Summary.pdf Documents/other/a
$ cp -a Documents/Pioneer\ Premier\ DEH-P490IB\ CD\ Install\ Manual.PDF  Documents/other/abc
$ find. -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
./Documents/other/abc

Eso es todo. Sé que probablemente me criticarán por ser horriblemente pedante, pero en mi trabajo con miles de volúmenes NFS para cazar y todo tipo de archivos mal -nombrados, desearía que más personas fueran pedantes.

Editado para agregar :en el mundo real, es posible que desee utilizar updatedbpara crear un índice de archivos de búsqueda, locateen lugar de findpara leer ese índice, y parallelen lugar de xargspara ensartarlo. Sin embargo, eso está fuera del alcance de esta pregunta. Escribí eso con una cara seria, también. ¿Por qué me importa tanto? Podría estar buscando archivos de películas y audio; o ciertos tipos de fotografías; o ejecutables binarios en un directorio de datos del proyecto.

2
20.05.2019, 23:20
1 ответ

Когда вы используете shift 2во внутреннем case, вы смещаете $1и $2, но не $3, имя файла.

Вам потребуется выполнить отдельный цикл для анализа параметров подкоманд mode1и mode2.

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

run_mode1 () {
    while [ "$#" -gt 0 ]; do
        case "$1" in
        -h | --help)
            usage_mode1
            exit
            ;;
        -1 | --option1)
            val1="$2"
            shift 2
            ;;
        -2 | --option2)
            val2="$2"
            shift 2
            ;;
        *)
            echo "ERROR: unknown parameter $1"
            usage_mode1
            exit 1
            ;;
        esac
    done

    # code for actually running mode1 goes here
}

while [[ $# -gt 0 ]]
do
    case "$1" in
    -h | --help)
        usage_general
        exit
        ;;

    mode1)
        shift
        run_mode1 "$@"
        break
        ;;

    *)
        echo "ERROR: unknown parameter $1"
        usage_general
        exit 1
        ;;
    esac
done

Здесь мы запускаем функцию оболочки, как только встречаем mode1среди аргументов командной строки. Эта функция занимается синтаксическим анализом остальной части списка аргументов.

Это, очевидно, будет работать только в определенных обстоятельствах, когда все опции для сценария(не для подкоманды )происходят до любой заданной подкоманды в командной строке, и что может быть только одна подкоманда с параметрами, заданными при любом вызове сценария.

Можно было бы реализовать парсинг командной строки таким образом, чтобы скрипт мог одновременно принимать две или более подкоманд с параметрами, как в

./script.sh...options... mode1...options... mode2...options...

но пока оставлю это.

2
27.01.2020, 22:17

Теги

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