При создании Firecode.io я недавно столкнулся с более чем сотней неудачных модульных тестов при запуске набора тестов локально на моем компьютере MacOS, а не в контейнере Linux Docker, в котором платформа настроена для запуска тестов.

Я использую MacBook Pro для разработки программного обеспечения, в первую очередь потому, что MacOS на основе BSD предоставляет возможности разработки, очень похожие на другие дистрибутивы Linux. Все мои наиболее часто используемые команды навигации cd, cp, mv, mkdir, touch, etc... работают с соотношением 1: 1 для обеих разновидностей операционных систем, по крайней мере, так я думал. Как я обнаружил, потратив хороший час на отладку этих сбоев, есть тонкая разница между реализациями команды cp -R в BSD и GNU, с которой я столкнулся при запуске моих тестов в разных средах.

Вот разница, показанная на примере работы как в MacOS, так и в Linux:

# Creates "source_directory" in the current working directory
$ mkdir source_directory
# Creates 2 new empty files within "source_directory"
$ touch source_directory/{file1,file2}
# Creates "destination_directory" in the current working directory
$ mkdir destination_directory
# Intended to copy the contents of "source_directory" to "destination_directory", hence the trailing slashes
$ cp -R source_directory/ destination_directory/
# Lists the contents of "destination_directory"
$ ls destination_directory

Итак, что вы ожидаете от печати с ls? Оказывается, реализация GNU для Linux cp копирует source_directory каталог в destination_directory, тогда как в MacOS BSD содержимое распаковывается и копируется, как я ожидал, это будет вести себя в обеих средах:

GNU (Linux):

$ ls destination_directory
source_directory

BSD (MacOS):

$ ls destination_directory
file1 file2

Завершающая косая черта важна в BSD, тогда как реализация GNU трактует как source_directory/, так и source_directory одинаково. К счастью, обходной путь очень прост - добавьте точку, когда вы собираетесь скопировать содержимое, и вы увидите одинаковое поведение как в BSD, так и в GNU: cp -R source_directory/. destination_directory/.

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