Perl - обнаружение символических ссылок под Windows 10 - PullRequest
0 голосов
/ 09 мая 2018

У меня проблема с обнаружением символических ссылок в Windows 10, которая их поддерживает. Сначала я попробовал это:

if(! -l $import_filename) {
    print "$0: $import_filename is not a symlink";
}

Это не работает. Он выполняется, когда $ import_filename является символической ссылкой. Тогда я попробовал это:

use File::stat;
use Fcntl;

my $statbuf = lstat($import_filename);
if(!($statbuf->mode & S_ISLNK)) {
    print "$0: $import_filename is not a symlink";
}

И, кажется, это другой способ сказать то же самое. Как и ожидалось, есть ли какой-нибудь благословенный способ сделать это под версиями Windows с поддержкой символической ссылки / соединения? Если нет, то инструмент командной строки также является приемлемым ответом.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

С учетом

>mklink file_symlink file
symbolic link created for file_symlink <<===>> file

>mklink /d dir_symlink dir
symbolic link created for dir_symlink <<===>> dir

>mklink /h file_hardlink file
Hardlink created for file_hardlink <<===>> file

>mklink /j dir_hardlink dir
Junction created for dir_hardlink <<===>> dir

>dir
...
2018-05-09  12:59 AM    <JUNCTION>     dir_hardlink [C:\...\dir]
2018-05-09  12:58 AM    <SYMLINKD>     dir_symlink [dir]
2018-05-09  12:56 AM                 6 file_hardlink
2018-05-09  12:58 AM    <SYMLINK>      file_symlink [file]
...

Вы можете использовать следующее для обнаружения file_symlink, dir_symlink и dir_hardlink (но не file_hardlink) как ссылки:

use Win32API::File qw( GetFileAttributes FILE_ATTRIBUTE_REPARSE_POINT );

my $is_link = GetFileAttributes($qfn) & FILE_ATTRIBUTE_REPARSE_POINT;

Я не знаю, как различить жесткие ссылки и символические ссылки (хотя различие между файлами и каталогами можно сделать с помощью & FILE_ATTRIBUTE_DIRECTORY).

0 голосов
/ 09 мая 2018

Похоже, что Perl не сильно поддерживает работу с символическими ссылками в Windows (если есть). В соответствии с perlport page для символической ссылки и для readlink ни одна из соответствующих встроенных функций не реализована.

Что наиболее важно для вашего прямого вопроса, lstat также не реализован , так что нельзя иметь тест файла для символической ссылки. perlport для -X говорит, что

-g, -k, -l, -u, -A не имеют особого значения.

Я ничего не нашел в CPAN, кроме использования Windows API.


Затем вы можете перейти к командной строке Windows и искать <SYMLINK> в dir output

# Build $basename and $path from $import_filename if needed
if ( not grep { /<SYMLINK>.*$basename/ } qx(dir $path) ) {
    say "$0: $import_filename is not a symlink";
}

, где необходимо использовать $basename, поскольку dir не показывает путь. Компоненты имени файла с полным путем могут быть получены, например, с помощью основного модуля File :: Spec

use File::Spec;
my ($vol, $path, $basename) = File::Spec->splitpath($import_filename);

Если имя файла не имеет пути, тогда $vol и $path являются пустыми строками, что нормально для dir, поскольку для текущего каталога не требуется аргументов. Если $import_filename по дизайну относится к текущему каталогу (без пути), используйте его в регулярном выражении с qx(dir) (без аргумента).

В выводе dir также отображается имя цели, что может пригодиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...