linux获取lnk文件的源目标路径,通过快捷方式lnk获得文件真实路径

通过快捷方式.lnk获得文件真实路径

前提

最近开发资源管理,需要预先上传大量资源,负责整理资源的同学因为空间不足,直接用快捷键方式整理视频资源OTZ,所以只能想办法通过.lnk文件获得文件的真实地址。

以下所有内容都来自网络,博主仅做了参考与总结。

.lnk文件格式解析

此处对lnk文件组成做一个大概介绍主旨是帮助了解如何从link文件中提取需要的信息

一个lnk文件包括一下几个模块:

模块 备注

e0993addeed5882318d9fffcc4101b31.png

注意:

不是所有的模块都必须包含在内,但如果存在就要按上述的顺序排列。

以下我们详细了解需要用到的两个模块:

1. 文件头(lnk file header)

偏移 长度 类型 备注

967edb1c544a386234ff94b1f990ca43.png

0x14处16进制数的含义:

5be749b49bf4c14f4de19754913f25fd.png

0x18处16进制数的含义:

ddffb0de20df7fc66469c7a25626bf98.png

2. 文件位置信息段(File location info)

20616bb203f48a3a897d278938ee990e.png

0x08偏移flags 具体含义:

如果目标文件是本地文件,那么文件名称 = 本地路径信息+剩余偏移路径

如果目标文件是网络文件,那么文件名称 = 网络卷中共享名称+剩余偏移路径

所以,File location info节之后的数据是,本地卷信息表,及网络卷信息表。

1. 本地卷信息表结构

f7e4aa95c8e151c4c787b849b19e3cd1.png

2. 网络卷信息表结构

2c7c0d4b8b9134a8a458bf56cc64d565.png

注意:

八个比特(Bit)称为一个字节(Byte),两个字节称为一个字(Word),两个字称为一个双字(Dword),两个双字称为一个四字(Qword)。

代码

private void parseLink(File f) throws FileNotFoundException, IOException {

FileInputStream fin = new FileInputStream(f);

byte[] link = new byte[(int)f.length()];

//读取文件中的内容到link[]数组

fin.read(link);

fin.close();

// 判断当前文件是否为快捷方式

if(!isLnkFile(link)){

return;

}

// 获得flags信息

byte flags = link[0x14];

int shell_len = 0;

// 0000 0000 xxxx xxxx & 0000 0000 0000 0001(判断是否包含shell item id list段)

if((flags & 0x1) > 0) {

// 如果存在,则获取shell item id list段的总长度,加2是为了将link[0x4c]本身的长度计算在内

shell_len = bytes2short(link,0x4c) + 2;

}

// 获得文件位置信息段的开始位置=shell item id list段的开始位置+shell item id list段的总长度

int file_start = 0x4c + shell_len;

// 获取本地路径信息的偏移

int local_sys_off = link[file_start + 0x10] + file_start;

String real_file = getNullDelimitedString(link, local_sys_off);

System.out.println(real_file);

}

private boolean isLnkFile(byte[] link) {

if (link[0x00]== 0x4c) {// 76,L,0x4c代表lnk文件格式

return true;

}

return false;

}

/**

* 将两个字节转换为short

* 注意,因为仅限英特尔操作系统,所以这是小端字节

*/

private int bytes2short(byte[] bytes, int off) {

return bytes[off] | (bytes[off + 1] << 8);

}

/**

* 获得从偏移位置off到以‘0’为结尾分割字符串

* @param bytes 源数组

* @param off 偏移位置

* @return 字符串

*/

private String getNullDelimitedString(byte[] bytes, int off) {

int len = 0;

// 计算字符串占用数组的真实长度

while (true) {

if (bytes[off + len] == 0) {

break;

}

len++;

}

byte[] results = new byte[len];

for (int i = off, j = 0; i < off + len; i++, j++) {

results[j] = bytes[i];

}

try {

// 因为我是中文系统,所以设置了字符集GBK,否则中文路径会出现乱码

return new String(bytes, off, len, "GBK");

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

return null;

}

import sys

import win32com.client

shell = win32com.client.Dispatch("WScript.Shell")

shortcut = shell.CreateShortCut("t:\\test.lnk")

print(shortcut.Targetpath)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值