сценарий оболочки с xargs и аргумент командной строки [duplicate]

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
24
задан eisaacson 18 October 2013 в 21:02
поделиться

2 ответа

Родительская оболочка, вызывающая bash show_files.sh *, расширяет * для вас.

В вашем скрипте вам нужно использовать:

for dir in "$@"
do
    echo "$dir"
done

Двойной кавычки гарантируют правильную обработку нескольких пробелов и т. д. в именах файлов.

См. также Как перебирать аргументы в сценарии оболочки bash .


Потенциально запутанное дополнение

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

names=( $@ )
for file in "${names[@]}"
do
    echo "$file"
done

Я не часто использую $@ без двойных кавычек, но это один раз, когда это более или менее правильная вещь для делать. Сложная часть состоит в том, что он не будет обрабатывать дикие карты с пробелами в очень хорошем состоянии.

Рассмотрим:

$ > "double  space.c"
$ > "double  space.h"
$ echo double\ \ space.?
double  space.c double  space.h
$

Это работает отлично. Но попробуйте передать это как wild-card для скрипта и ... ну, давайте просто скажем, что в этот момент это будет сложно.

Если вы хотите извлечь $2 отдельно, то вы можете использование:

names=( $1 )
for file in "${names[@]}"
do
    echo "$file"
done
# ... use $2 ...
39
ответ дан Community 18 August 2018 в 15:55
поделиться
  • 1
    Большой! Есть ли способ сделать это, что позволит использовать несколько параметров. Например, bash show_files.sh * second_param. Это приложение действительно не нуждается в этом. Просто любопытно. – eisaacson 18 October 2013 в 21:12
  • 2
    @eisaacson, если second_param на первом месте, вы можете сделать sparam=$1; shift;, затем использовать $@. – jordanm 18 October 2013 в 21:24
  • 3
    @jordanm Ваш комментарий здесь - отличное решение. Спасибо. – eisaacson 18 October 2013 в 22:28
  • 4
    @JonathanLeffler Что вы добавили в свой ответ, все это очень запутывает. – eisaacson 18 October 2013 в 22:29
  • 5
    Сожалею; это не было целью. Прохождение wild-cards вокруг - это не очень хорошая идея, отчасти потому, что это делает все очень запутанным. Пусть оболочка справится с ней естественным образом. В своем дизайне сначала передайте параметр «второй», и оставьте «список файлов / каталогов» в качестве остальной части аргументов. Это естественный дизайн Unix. Я бы рекомендовал использовать его, если это вообще возможно. – Jonathan Leffler 18 October 2013 в 22:52

Введите wild-card:

bash show_files.sh '*'

или сделайте свой сценарий принятым списком аргументов, а не только одним:

for dir in "$@"
do
    echo "$dir"
done

Лучше итерации непосредственно над "$@' вместо того, чтобы назначать его другой переменной, чтобы сохранить свою особую способность удерживать элементы, которые сами содержат пробелы.

8
ответ дан chepner 18 August 2018 в 15:55
поделиться
  • 1
    Большой! Второй вариант идеален. Есть ли способ сделать это, что позволит использовать несколько параметров. Например, bash show_files.sh * second_param. Это приложение действительно не нуждается в этом. Просто любопытно. – eisaacson 18 October 2013 в 21:12
  • 2
    Вид. Ваш скрипт получит переменное количество параметров, с тем, что вы называете «second_param». действительно являющийся параметром last . show_files.sh никогда не видит *, а только список файлов, к которым оболочка расширяет его. Немного сложно получить последний аргумент, хотя bash имеет некоторые расширения, чтобы упростить его. ${@: -1} (необходимое пространство) даст вам последний аргумент. ${@:0:$#}, кажется, дает вам все , но последнее, но использование смещения 0 с $@ (которое в остальном является массивом на основе 1) кажется немного подозрительным, и это выражение может быть ошибочным. – chepner 18 October 2013 в 21:25
  • 3
    Для меня первый вариант идеален. Мне нужно было передать параметр другому скрипту, который самостоятельно обрабатывает подстановочные знаки. – mirelon 27 December 2013 в 22:07