No lo harás a menos que lo pidas. Claro, estoy siendo pedante, pero no preguntaste sobre los archivos con .pdf
en sus nombres . El hecho de que un archivo tenga los caracteres .pdf
en 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 -iname
podrí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 find
luego 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 a
yabc
:
$ 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 updatedb
para crear un índice de archivos de búsqueda, locate
en lugar de find
para leer ese índice, y parallel
en lugar de xargs
para 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.
Когда вы используете 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...
но пока оставлю это.