Извлечь имя файла из пути в программе awk

21

У меня есть сценарий awk, и я передал ему файл CSV.

awk -f script.awk /home/abc/imp/asgd.csv

Что я делаю, чтобы получить FILENAME внутри script.awk. FILENAME дает мне весь путь. Поскольку я нахожусь в awk, я не могу использовать basename FILENAME.

print FILENAME;
/home/abc/imp/asgd.csv

Я пытался с этим в течение script.awk

echo $FILENAME | awk -F"/" '{print $NF}'

но я не могу выполнить это внутри script.awk. Как я могу попасть asgd.csvв программу awk?

Aashu
источник

Ответы:

33

Несколько вариантов:

awk '
  function basename(file) {
    sub(".*/", "", file)
    return file
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file

Или:

awk '
  function basename(file, a, n) {
    n = split(file, a, "/")
    return a[n]
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file

Обратите внимание, что эти реализации basenameдолжны работать для общих случаев, но не в угловых случаях, например, basename /path/to/x///когда они возвращают пустую строку вместо xили /когда они возвращают пустую строку вместо /, хотя для обычных файлов это не должно происходить.

Первый из них не будет работать должным образом, если пути к файлам (до последнего /) содержат последовательности байтов, которые не образуют допустимых символов в текущей локали (обычно такого рода вещи случаются в локалях UTF-8 с именами файлов, закодированными в некоторых 8 битовый однобайтовый набор символов). Вы можете обойти это, установив локаль на C, где каждая последовательность байтов образует допустимые символы.

Стефан Шазелас
источник
5
Если вам нужен код , который будет работать легко в пределах существующего AWK сценария без введения функции, вы должны использовать: n = split(FILENAME, a, "/"); basename=a[n];. Не используйте, так subкак это на самом деле изменит FILENAMEпеременную (что не является проблемой для функции, так как awk использует вызов по значению).
Шири
10

Попробуй это awk one-liner,

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
asgd.csv
Авинаш Радж
источник
3
илиawk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv
Авинаш Радж
0

лучший способ экспортировать его из входного CSV или напрямую из пути к входному файлу - это отменить его, затем получить 1 столбец и затем снова перевернуть его.

function getFileFromPath() {
    FileName=$1
    cat $FileName | while read Filename
    do
        echo $Filename| rev | awk -v FS='/' '{print $1}' | rev 
    done
}

или просто

echo $FileNamePath| rev | awk -v FS='/' '{print $1}' | rev 
Фариз
источник
0

Используйте функцию разделения Awk

Один из способов сделать это - использовать функцию split. Например:

awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' /path/to/file

Это даже работает на нескольких файлах. Например:

$ awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' \
      /etc/passwd /etc/group
passwd
group
CodeGnome
источник
0

В системах , где basenameкоманда доступна, можно использовать awk«s system()функцию или expression | getline varструктуру для вызова внешней basenameкоманды. Это может помочь в учете угловых случаев, упомянутых в ответе Стефана .

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Сергей Колодяжный
источник