PHP, lấy tên tệp mà không cần mở rộng tệp


205

Tôi có mã PHP này:

function ShowFileExtension($filepath)
{
    preg_match('/[^?]*/', $filepath, $matches);
    $string = $matches[0];

    $pattern = preg_split('/\./', $string, -1, PREG_SPLIT_OFFSET_CAPTURE);

    if(count($pattern) > 1)
    {
        $filenamepart = $pattern[count($pattern)-1][0];
        preg_match('/[^?]*/', $filenamepart, $matches);
        return strtolower($matches[0]);
    }
}

Nếu tôi có một tệp có tên my.zip, hàm này trả về .zip.

Tôi muốn làm ngược lại, tôi muốn hàm trả về mymà không cần phần mở rộng.

Các tập tin chỉ là một chuỗi trong một biến.


Câu trả lời:


397

Không cần tất cả điều đó. Kiểm tra pathinfo () , nó cung cấp cho bạn tất cả các thành phần của đường dẫn của bạn.

Ví dụ từ hướng dẫn:

$path_parts = pathinfo('/www/htdocs/index.html');

echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // filename is only since PHP 5.2.0

Đầu ra của mã:

/www/htdocs
index.html
html
index

Và ngoài ra, bạn chỉ có thể nhận được một số phần nhất định như:

echo pathinfo('/www/htdocs/index.html', PATHINFO_EXTENSION); // outputs html

3
Tại sao điều này bị hạ cấp? Câu trả lời là hoàn toàn chính xác. pathinfo hoạt động trên các chuỗi, vì vậy không có vấn đề gì nếu tập tin thực sự nằm trên máy chủ hay không.
Gordon

13
Thật không may là họ đã đặt tên sai là "tên cơ sở", vì nó trả về tên tệp đầy đủ với phần mở rộng, không phải tên cơ sở.
Oscar

1
@Oscar nó là nghĩa được hiểu rộng rãi nhất của thuật ngữ này basename. Không đặt tên sai.
nawfal

1
Điều này rất hữu ích, đặc biệt là khi bạn không cần biết phần mở rộng tệp để giải nén nó.
Vahid Amiri

Đây là một giải pháp cực kỳ thanh lịch. Thanh danh. Điều này nên được đánh dấu là câu trả lời chính xác.
bản địa

199

Thay thế cho pathinfo(), bạn có thể sử dụng

  • basename() - Trả về thành phần tên tệp của đường dẫn

Ví dụ từ hướng dẫn sử dụng PHP

$path = "/home/httpd/html/index.php";
$file = basename($path);         // $file is set to "index.php"
$file = basename($path, ".php"); // $file is set to "index"

Bạn phải biết phần mở rộng để loại bỏ nó trước mặc dù.

Tuy nhiên, vì câu hỏi của bạn cho thấy bạn có nhu cầu nhận tiện ích mở rộng tên cơ sở, tôi sẽ bình chọn câu trả lời của Pekka là hữu ích nhất, bởi vì nó sẽ cung cấp cho bạn bất kỳ thông tin nào bạn muốn về đường dẫn và tệp với một bản địa duy nhất chức năng.


1
Điều gì xảy ra nếu tôi không biết về phần mở rộng tập tin .. giả sử nếu đường dẫn là bất kỳ loại phần mở rộng tập tin nào có thể đi vào đó !! rồi sao ??
dùng889030

@ user889030 thì bạn có một kịch bản khác với OP và không sử dụng basename, nhưng pathinfonhư được hiển thị khác trên trang.
Gordon

72

https://php.net/manual/en/feft.pathinfo.php

pathinfo($path, PATHINFO_FILENAME);

Kiểm tra chức năng đơn giản: https://ideone.com/POhIDC


Điều này sẽ trả về tên tệp phần mở rộng
user966939

2
@ user966939 Mhh, không tiện ích mở rộng là basename;-)
yckart

Dù sao đi nữa, anh ấy đang yêu cầu một giải pháp KHÔNG CÓ phần mở rộng. ;)
dùng966939

2
@ user966939, Dude không có phần mở rộng nào cả. Đó là PATHINFO_FILENAME, không phải PATHINFO_EXTENSION ....
Pacerier

20
Bất cứ ai quyết định filenamekhông gia hạn trong khi basenamephải có một số xu hướng tàn bạo ...
Đánh dấu

12

Một cách tiếp cận khác là sử dụng các biểu thức thông thường.

$fileName = basename($filePath);
$fileNameNoExtension = preg_replace("/\.[^.]+$/", "", $fileName);

Điều này loại bỏ từ giai đoạn cuối cùng .cho đến khi kết thúc chuỗi.


Tôi thích câu trả lời này, rất đơn giản và hoạt động khi bạn không biết tiện ích mở rộng.
tái hiện

Tốt hơn nhiều so với sử dụng phát nổ và chỉ bắt được phần thời gian cuối cùng trong trường hợp bạn đã sử dụng dấu
chấm

7
Không , nó tệ hơn nhiều. Ngừng regexing mọi người.
Pacerier

Cảm ơn, và các ý kiến ​​trên đóng đinh nó. Không phải biết phần mở rộng làm cho điều này hữu ích hơn.
James Taylor

1
@ caiosm1005, Bề mặt tấn công ngay lập tức tăng lên vì khó có thể chống lại các phần bên trong của một công cụ regex. Ví dụ, trong đoạn mã trên, sẽ không có gì lạ nếu có một số đầu vào $fileNamecó thể khiến động cơ chạy theo thời gian theo cấp số nhân (hoặc tệ hơn). Và giả sử chúng ta đã hoàn thành việc mổ xẻ phần bên trong của công cụ regex cụ thể này và về mặt lý thuyết đã chứng minh rằng nó mạnh mẽ chống lại mọi giá trị $fileNamecó thể, mã vẫn không thể tùy ý chuyển sang nền tảng khác có triển khai công cụ regex khác.
Pacerier

12

Nếu phần mở rộng không được biết, sử dụng giải pháp này

 pathinfo('D:/dir1/dir2/fname', PATHINFO_FILENAME); // return "fname"
 pathinfo('D:/dir1/dir2/fname.php', PATHINFO_FILENAME); // return "fname"
 pathinfo('D:/dir1/dir2/fname.jpg', PATHINFO_FILENAME); // return "fname"

 pathinfo('D:/dir1/dir2/fname.jpg', PATHINFO_DIRNAME) . '/' . pathinfo('D:/dir1/dir2/fname.jpg', PATHINFO_FILENAME); // return "D:/dir1/dir2/fname"

Đường dẫn chức năng PHP MAN


Vui lòng cung cấp một thích cho trang man php cho pathinfo. Điều này sẽ giúp OP làm cho ShowFileExtensionphương pháp tốt hơn và sẽ cung cấp thêm đọc cho bất cứ ai cố gắng tìm câu trả lời này. Ngoài ra một chút mô tả sẽ không đi lạc đường ...
Michael Coxon

1
Tôi đã trả lời câu hỏi này với cùng một giải pháp, ~ 2 năm trước câu hỏi của bạn;)
yckart

@yckart đúng nhưng điều này không đưa ra nhiều ví dụ trong câu trả lời. Bạn có lợi ích khi liên kết với ideone.com nhưng trang web có thể hoạt động ngoại tuyến.
Adam Elsodaney

7

Tên cơ sở @Gordon sẽ hoạt động tốt nếu bạn biết tiện ích mở rộng, nếu không, bạn có thể sử dụng explode:

$filename = end(explode(".", $file));

1
Hãy bình luận trực tiếp cho tôi với chức năng bình luận bên dưới câu trả lời của tôi. Chức năng thích hợp nhất cho việc này là pathinfo, đó là lý do tại sao tôi chỉ đưa ra basenamemột giải pháp thay thế. Không cần phải phát minh lại pathinfovới regex hay explode.
Gordon

4
@fire, cập nhật của bạn không có ý nghĩa. end(explode(".", $file));cung cấp cho bạn phần mở rộng, không phải tên tệp.
Pacerier

7

Hầu như tất cả các giải pháp trên đều có tên tệp được hiển thị từ biến $ path

Đoạn mã dưới đây sẽ nhận được tên tệp được thực hiện hiện tại mà không cần gia hạn

echo pathinfo(basename($_SERVER['SCRIPT_NAME']), PATHINFO_FILENAME);

Giải trình

$ _SERVER ['SCRIPT_NAME'] chứa đường dẫn của tập lệnh hiện tại.



4

@fire bao gồm tên tệp sử dụng dấu chấm, bạn có thể nhận được đầu ra sai. Tôi sẽ sử dụng phương thức @Gordon nhưng cũng nhận được phần mở rộng, vì vậy hàm basename hoạt động với tất cả các phần mở rộng, như thế này:

$path = "/home/httpd/html/index.php";
$ext = pathinfo($path, PATHINFO_EXTENSION);

$file = basename($path, ".".$ext); // $file is set to "index"

4

trong trường hợp của tôi, tôi sử dụng dưới đây. Tôi không quan tâm đến sự kéo dài của nó là gì. : D tôi nghĩ nó sẽ giúp bạn

$exploded_filepath = explode(".", $filepath_or_URL);
$extension = end($exploded_filepath);
echo basename($filepath_or_URL, ".".$extension ); //will print out the the name without extension.

Btw.: Bạn có một lỗi đánh máy trong$extenion
Thomas Kekeisen

2

Bạn có thể viết cái này

$filename = current(explode(".", $file));

Chúng sẽ trả về phần tử hiện tại của mảng, nếu không được sử dụng trước đó.


Xin chào, xin vui lòng kiểm tra trước khi hạ cấp nó. Nó đang hoạt động tôi đã sử dụng nó trong mã của tôi nhiều lần. Bằng cách sử dụng chức năng này, bạn có thể chỉ nhận được một tên tệp Nếu tên tệp của bạn là "xyz.jpg". Nó có thể không hoạt động với tên tệp chứa toàn bộ đường dẫn trong đó.
Jitendra Pawar

Điều này cũng không hoạt động chính xác nếu tên tệp có nhiều dấu chấm trong đó, ví dụ: "some.interesting.image.jpg"
ganzpopp

2

Ngắn

echo pathinfo(__FILE__)['filename']; // since php 5.2

tốt Nhưng nếu tôi đặt mã ở trên b.phpvà tôi thực hiện a.phprequire('b.php'). Sau đó, đầu ra sẽ như thế nào bthay vìa
Rohan Khude

1

Tên tệp không có phần mở rộng tệp khi bạn không biết phần mở rộng đó:

$basename = substr($filename, 0, strrpos($filename, "."));


2
Nếu phần mở rộng giống như .tar.gz thì sao?
Arda

1

Nếu bạn không biết bạn có tiện ích mở rộng nào, thì bạn có thể thử điều này:

$ext = strtolower(substr('yourFileName.ext', strrpos('yourFileName.ext', '.') + 1));
echo basename('yourFileName.ext','.'.$ext); // output: "youFileName" only

Làm việc với tất cả các khả năng:

image.jpg // output: "image"
filename.image.png // output: "filename.image"
index.php // output: "index"

1

Câu trả lời của bạn nằm dưới giải pháp hoàn hảo để ẩn phần mở rộng tệp trong php.

<?php
    $path = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    echo basename($path, ".php");
?>

1

Các giải pháp hiện có không thành công khi có nhiều phần cho một phần mở rộng. Hàm bên dưới hoạt động cho nhiều phần, đường dẫn đầy đủ hoặc chỉ một tên tệp:

function removeExt($path)
{
    $basename = basename($path);
    return strpos($basename, '.') === false ? $path : substr($path, 0, - strlen($basename) + strlen(explode('.', $basename)[0]));
}

echo removeExt('https://example.com/file.php');
// https://example.com/file
echo removeExt('https://example.com/file.tar.gz');
// https://example.com/file
echo removeExt('file.tar.gz');
// file
echo removeExt('file');
// file

0

Điều này chỉ trả về tên tệp mà không có bất kỳ phần mở rộng nào trong 1 hàng:

$path = "/etc/sudoers.php";    
print array_shift(explode(".", basename($path)));
// will print "sudoers"

$file = "file_name.php";    
print array_shift(explode(".", basename($file)));
// will print "file_name"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.