Ubuntu 17.04 - bash: cd: слишком много аргументов

10

Я только что обновил свой Ubuntu 16.04 до 17.04 и обнаружил небольшую проблему с cdкомандой.

Допустим, у меня есть две папки: album-01&album-02

В Ubuntu 16.04, если я cd album*это сделаю, я пойду в первую найденную папкуalbum-01

Но в новой Ubuntu 17.04, если я это сделаю, cd album*приведи меня -bash: cd: too many arguments

Как сделать cdв Ubuntu 17.04 как cdв Ubuntu 16.04?

Hidayats
источник
4
То, что вы получаете, имеет смысл, поскольку вы даете cdдва местоположения и каким-то образом ожидаете, что оно определит, какое вы хотите.
Во всяком случае,
1
К сожалению, руководство Bash не соглашается с вами: «Любые дополнительные аргументы, следующие за каталогом , игнорируются»
muru
3
Опубликовал отчет об ошибке на тот случай, если кому-то будет интересно: bugs.launchpad.net/ubuntu/+source/bash/+bug/1683576
17
Пожалуйста, не забудьте принять ответ, который вам больше всего помог, щелкнув по серой круглой кнопке слева, если ваш вопрос решен удовлетворительно.
Byte Commander

Ответы:

9

Я не мог проверить это на реальной системе 17.04 (только проверил, что она работает на 16.04), но вы должны иметь возможность переопределить cdвстроенную команду Bash своей собственной пользовательской функцией, которая отбрасывает любые дополнительные аргументы, кроме первого :

cd(){ command cd "$1" ; }

Обновление: Как предлагается в комментарии @ muru , эта версия ниже может работать лучше и поддерживать вызов cdбез аргументов:

cd(){ builtin cd "${@:1:1}"; }

После того, как вы ввели эту строку выше в своем терминале, пожалуйста, проверьте, cdведет ли себя теперь так, как вы хотите. Если это так, вы можете сделать это определение функции постоянным, добавив эту строку в конец вашего ~/.bashrcфайла. В противном случае он исчезнет, ​​как только вы закончите текущий сеанс оболочки.

Обратите внимание, что если по какой-либо причине вам временно понадобится использовать настоящую cdвстроенную команду Bash вместо этой пользовательской функции, вы можете просто вызвать ее command cdвместо обычного cd.

Byte Commander
источник
Я писал то же самое, вместо функции я предлагал псевдоним для крошечного скрипта ... уверен, что он работает;)
Ravexina
@Ravexina Я тоже сначала подумал об использовании псевдонима, но потом отбросил его, потому что думаю, что это невозможно сделать с псевдонимом, потому что там у вас нет контроля над аргументами. Просто из любопытства, какой подход вы бы предложили?
Byte Commander
Я сделал то же самое, я просто поместил код в .shфайл, а затем создал псевдоним:mcd="source /home/user/bin/cd.sh"
Ravexina
Ах хорошо. Это немного сложнее, чем нужно, но должно работать.
Byte Commander
2
@SandiHidayat Попробуйте cd () { builtin cd "${@:1:1}"; }вместо этого.
Муру
7

Краткий ответ / Обходной путь

Чтобы ответить на ваш вопрос в этом конкретном случае, это работает

cd album*1

Но это, вероятно, не та функциональность, которую вы действительно хотите.

Что изменилось?

Похоже, что config-top.hв Bash-4.4 было обновлено добавить следующую опцию

/* Define CD_COMPLAINS if you want the non-standard, but sometimes-desired
   error messages about multiple directory arguments to `cd'. */

#define CD_COMPLAINS

И builtins/cd.defотносится к вашей ошибке здесь:

#if defined (CD_COMPLAINS)
  else if (list->next)
    {
      builtin_error (_("too many arguments"));
      return (EXECUTION_FAILURE);
    }
#endif

Что я могу сделать в долгосрочной перспективе?

Вы можете скомпилировать свой собственный bashбез нового CD_COMPLAINS , но это будет утомительно. Вы можете переопределить cdфункциональность, как предложено здесь, или вы можете использовать псевдоним функции, как

cd "$(find $1* | head -1)"

Доказать это

Bash 4.4 Beta, где он все еще работает

#Pulling and unpacking source
$ wget https://ftp.gnu.org/gnu/bash/bash-4.4-beta.tar.gz
$ tar -xzvf bash-4.4-beta.tar.gz
$ cd bash-4.4-beta

#Building, go grab something to drink. It's gonna be a while.
~/bash-4.4-beta$ ./configure
~/bash-4.4-beta$ make

#Check Version
~/bash-4.4-beta$ ./bash --version
GNU bash, version 4.4.0(1)-beta (x86_64-unknown-linux-gnu)

#Enter a clean interactive prompt
~/bash-4.4-beta$ env -i PATH="$PWD:$PATH" ./bash --noprofile --norc

#Test example
bash-4.4$ mkdir album-0{1..2}
bash-4.4$ cd album* && pwd
/home/gkent/bash-4.4-beta/album0-1

Bash 4.4 Stable Release там, где он не работает

#Pulling and unpacking source
$ wget https://ftp.gnu.org/gnu/bash/bash-4.4.tar.gz
$ tar -zxvf bash-4.4.tar.gz
$ cd bash-4.4/

#Building, go grab something to drink. It's gonna be a while.
~/bash-4.4$ ./configure
~/bash-4.4$ make

#Check Version
~/bash-4.4$ ./bash -version
GNU bash, version 4.4.0(1)-release (x86_64-unknown-linux-gnu)

#Enter a clean interactive prompt
~/bash-4.4$ env -i PATH="$PWD:$PATH" ./bash --noprofile --norc

#Test example
bash-4.4$ mkdir album-0{1..2}
bash-4.4$ cd album*
bash: cd: too many arguments
Грейсон Кент
источник
Извините, была опечатка. Обновленный ответ.
Грейсон Кент
Ах, верно. Вы могли бы просто сделать cd alb*1, чтобы соответствовать литералу 1в конце, даже без скобок. Сначала я перепутал вашу идею с чем-то другим.
ilkkachu
5

Я никогда не сталкивался с этой проблемой, так как я всегда использую Tab Completion.

Таким образом, в вашем случае, вместо того, чтобы иметь неточное предположение о том, какой каталог я хочу, я бы напечатал, cd alTabкоторый, если есть только одно совпадение, завершает его, и если есть 2 или более завершений, до того места, где заканчивается сопоставление, и TabTabперечисляет варианты.

Вот пример из моей системы:

cd Un Tab

cd Unknown

после чего TabTabпроизводит

Unknown/                        Unknown Artist - Unknown Album/ 
Старейшина Гик
источник
2

Это похоже на ошибку в Bash: согласно man builtinsстарому поведению правильное.

   cd [-L|[-P [-e]] [-@]] [dir]
              Change the current directory to dir.  if dir is not supplied,
              the  value  of  the  HOME shell variable is the default.  Any
              additional arguments following dir are ignored.

Вы можете сообщить об ошибке в bug-bashсписке рассылки; подробнее здесь .


Собственно, об ошибке сообщалось (давно). Если вам нужен исправленный Bash сейчас, сейчас, сейчас , вот как это сделать правильно (протестировано 17.10, должно работать и на других).

Сначала создайте каталог для работы, например:

mkdir ~/bash
cd ~/bash

Получите исходный пакет и зависимости сборки:

apt-get source bash
sudo apt-get build-dep bash
cd bash-4.4

Изменить, config-top.hчтобы изменить это (должно быть строка 32)

#define CD_COMPLAINS

к этому

/* #define CD_COMPLAINS */

Отредактируйте debian/changelogи добавьте такую ​​запись вверху (вы также можете использовать команду dch -i):

bash (4.4-5ubuntu1+cd) artful; urgency=medium

  * Fix cd.

 -- Firas Kraiem <firas@fkraiem.org>  Thu, 04 Jan 2018 21:11:22 +0900

Наиболее важными моментами являются добавление +fooк текущему номеру версии (это fooможет быть любая строка строчных букв; будьте осторожны, если вы используете dch -i, она увеличит последний номер, поэтому вам нужно вернуть его к текущему) и использовать правильное название релиза ( artfulздесь). Наконец, беги dpkg-source --commit.

Затем вы можете запустить debuildкоманду, и, если все пойдет хорошо (ошибки об этом debsignмогут быть проигнорированы), вы должны иметь некоторые .debs в родительском каталоге, которые вы можете установить как обычно (нет необходимости устанавливать все из них, только те, которые вы теперь, используйте, dpkg -l | grep bashчтобы узнать).

Обратите внимание, что номер версии нового пакета установлен так, что вы будете автоматически получать любые последующие обновления bash; Если обновление не устраняет проблему, вам необходимо повторить описанный выше процесс.

(Этот ответ был впервые опубликован на этот дубликат вопроса .)

fkraiem
источник