---
title: "List file properties"
section: "frontend/storage"
platforms: ["android", "angular", "flutter", "javascript", "nextjs", "react", "react-native", "swift", "vue"]
gen: 2
last-updated: "2026-03-25T17:40:00.000Z"
url: "https://docs.amplify.aws/react/frontend/storage/list-files/"
---

You can list files without having to download all the files. You can do this by using the `list` API from the Amplify Library for Storage. <!-- Platform: react, angular, javascript, vue, nextjs, react-native -->
You can also get properties individually for a file using the `getProperties` API.
<!-- /Platform -->

## List Files

<!-- Platform: react, angular, javascript, vue, nextjs, react-native -->
```javascript
import { list } from 'aws-amplify/storage';

const result = await list({
	path: 'album/photos/',
  // Alternatively, path: ({identityId}) => `album/${identityId}/photos/`
});
```

Note the trailing slash `/` - if you had requested `list({ path :  'album/photos' })` it would also match against files like `album/photos123.jpg` alongside `album/photos/123.jpg`.

The format of the response will look similar to the below example:

```js
{
  items: [
    {
      path: "album/photos/123.jpg",
      eTag: "30074401292215403a42b0739f3b5262",
      lastModified: "Thu Oct 08 2020 23:59:31 GMT+0800 (Singapore Standard Time)",
      size: 138256
    },
    // ...
  ],
}
````

If the `pageSize` is set lower than the total file size, a single `list` call only returns a subset of all the files. To list all the files with multiple calls, users can use the `nextToken` flag:

```javascript
import { list } from 'aws-amplify/storage';

const PAGE_SIZE = 20;
let nextToken;
// ...
const loadNextPage = async () => {
  const response = await list({
    path: 'photos/',
    // Alternatively, path: ({ identityId }) => `album/${identityId}/photos/`
    options: {
      pageSize: PAGE_SIZE,
      nextToken,
    },
  });
  if (response.nextToken) {
    nextToken = response.nextToken;
  } else {
    nextToken = undefined;
  }
  // render list items from response.items
};
```

### List All files
```javascript
import { list } from 'aws-amplify/storage';

const result = await list({
	path: 'album/photos/',
  // Alternatively, path: ({identityId}) => `album/${identityId}/photos/`,
  options: {
    listAll: true,
  }
});
```

 Manually created folders will show up as files with a `size` of 0, but you can also match keys against a regex like `file.key.match(/\.[0-9a-z]+$/i)` to distinguish files from folders. Since "folders" are a virtual concept in Amazon S3, any file may declare any depth of folder just by having a `/` in its name.

To access the contents and subpaths of a "folder", you have two options:

1. Request the entire path and parse the contents.
2. Use the subpathStrategy option to retrieve only the files within the specified path (i.e. exclude files under subpaths).

### Get all nested files within a path

This retrieves all files and folders under a given path. You may need to parse the result to get only the files within the specified path.

```js
function processStorageList(response) {
  let files = [];
  let folders = new Set();
  response.items.forEach((res) => {
    if (res.size) {
      files.push(res);
      // sometimes files declare a folder with a / within then
      let possibleFolder = res.path.split('/').slice(0, -1).join('/');
      if (possibleFolder) folders.add(possibleFolder);
    } else {
      folders.add(res.path);
    }
  });
  return { files, folders };
}
```

If you need the files and folders in terms of a nested object instead (for example, to build an explorer UI), you could parse it recursively:

```js
function processStorageList(response) {
  const filesystem = {};
  // https://stackoverflow.com/questions/44759750/how-can-i-create-a-nested-object-representation-of-a-folder-structure
  const add = (source, target, item) => {
    const elements = source.split('/');
    const element = elements.shift();
    if (!element) return; // blank
    target[element] = target[element] || { __data: item }; // element;
    if (elements.length) {
      target[element] =
        typeof target[element] === 'object' ? target[element] : {};
      add(elements.join('/'), target[element], item);
    }
  };
  response.items.forEach((item) => add(item.path, filesystem, item));
  return filesystem;
}
```

This places each item's data inside a special `__data` key.

### Excluding subpaths

In addition to using the `list` API to get all the contents of a path, you can also use it to get only the files within a path while excluding files under subpaths.

For example, given the following keys in your `path` you may want to return only the jpg object, and not the "vacation" subpath and its contents:

```
photos/photo1.jpg
photos/vacation/
```

This can be accomplished with the `subpathStrategy` option:

```ts title="src/main.ts"
import { list } from "aws-amplify/storage";
const result = await list({ 
  path: "photos/",
  options:{
    subpathStrategy: { strategy:'exclude' }
  }
});
```

The response will include only the objects within the `photos/` path and will also communicate any excluded subpaths:

```js
{
    excludedSubpaths: [
      'photos/vacation/'
    ],
    items: [
      {
        path: "photos/photo1.jpg",
        eTag: "30074401292215403a42b0739f3b5262",
        lastModified: "Thu Oct 08 2020 23:59:31 GMT+0800 (Singapore Standard Time)",
        size: 138256
      },
    ]
}
```

The default delimiter character is '/', but this can be changed by supplying a custom delimiter:

```ts title="src/main.ts"
const result = await list({
  // Path uses '-' character to organize files rather than '/'
  path: 'photos-',
  options: {
    subpathStrategy: {
      strategy: 'exclude',
      delimiter: '-'
    }
  }
});
```

### List files from a specified bucket

You can also perform an `copy` operation to a specific bucket by providing the `bucket` option. This option can either be a string representing the target bucket's assigned name in Amplify Backend or an object specifying the bucket name and region from the console.

```ts
import { list } from 'aws-amplify/storage';

const result = await list({
  path: 'photos/',
  options: {
    // Specify a target bucket using name assigned in Amplify Backend
    bucket: 'assignedNameInAmplifyBackend',
    // Alternatively, provide bucket name from console and associated region
    // bucket: {
    //   bucketName: 'generated-secondary-bucket-name',
    //   region: 'us-east-2'
    // }
  }
});
```

### More `list` options

| Option | Type | Default | Description |
| -- | :--: | :--: | ----------- |
| bucket | string \| <br />\{ bucketName: string;<br/> region: string; \} | Default bucket and region from Amplify configuration | A string representing the target bucket's assigned name in Amplify Backend or an object specifying the bucket name and region from the console.<br/><br/>Read more at [Configure additional storage buckets](/[platform]/build-a-backend/storage/set-up-storage/#configure-additional-storage-buckets) |
| listAll | boolean | false | Set to true to list all files within the specified `path` |
| pageSize | number | 1000 | Sets the maximum number of files to be return. The range is 0 - 1000 |
| nextToken | string | — | Indicates whether the list is being continued on this bucket with a token |
| subpathStrategy | \{ strategy: 'include' \} \|<br/>\{ 'exclude',<br />delimiter?: string \} | \{ strategy: 'include' \} | An object representing the subpath inclusion strategy and the delimiter used to group results for exclusion. <br/><br/> Read more at [Excluding subpaths](/[platform]/frontend/storage/list-files/#excluding-subpaths) |
| useAccelerateEndpoint | boolean | false | Whether to use accelerate endpoint. <br/><br/> Read more at [Transfer Acceleration](/[platform]/build-a-backend/storage/extend-s3-resources/#example---enable-transfer-acceleration) |
| expectedBucketOwner | string | Optional | The account ID that owns requested bucket. |
<!-- /Platform -->

<!-- Platform: android -->
The following example lists all objects inside the `public/photos/` path:

#### [Java]

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .build();

Amplify.Storage.list(
    StoragePath.fromString("public/photos/"),
    options,
    result -> {
        for (StorageItem item : result.getItems()) {
            Log.i("MyAmplifyApp", "Item: " + item.getPath());
        }
        Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
    },
    error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

#### [Kotlin - Callbacks]

```kotlin
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .build()

Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
    { result ->
        result.items.forEach { item ->
            Log.i("MyAmplifyApp", "Item: ${item.path}")
        }
        Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
    },
    { Log.e("MyAmplifyApp", "List failure", it) }
)
```

#### [Kotlin - Coroutines]

```kotlin
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .build()

try {
    val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
    result.items.forEach {
        Log.i("MyAmplifyApp", "Item: $it")
    }
    Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
    Log.e("MyAmplifyApp", "List failure", error)
}
```

#### [RxJava]

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
        .setPageSize(1000)
        .build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
        .subscribe(
            result -> {
                for (StorageItem item : result.getItems()) {
                    Log.i("MyAmplifyApp", "Item: " + item.getPath());
                }
                Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
            },
            error -> Log.e("MyAmplifyApp", "List failure", error);
        );
```

<Callout>
Note the trailing slash `/` in the given path.

If you had used `public/photos` as path, it would also match against files like `public/photos01.jpg`.
</Callout>

### List files from a specified bucket

You can also perform a list operation to a specific bucket by providing the `bucket` option. You can pass in a string representing the target bucket's assigned name in Amplify Backend.

#### [Java]

```java
StorageBucket secondBucket = StorageBucket.fromOutputs("secondBucket");
StoragePagedListOptions options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .bucket(secondBucket)
    .build();

Amplify.Storage.list(
    StoragePath.fromString("public/photos/"),
    options,
    result -> {
        for (StorageItem item : result.getItems()) {
            Log.i("MyAmplifyApp", "Item: " + item.getPath());
        }
        Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
    },
    error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

#### [Kotlin - Callbacks]

```kotlin
val secondBucket = StorageBucket.fromOutputs("secondBucket")
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .bucket(secondBucket)
    .build()

Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
    { result ->
        result.items.forEach { item ->
            Log.i("MyAmplifyApp", "Item: ${item.path}")
        }
        Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
    },
    { Log.e("MyAmplifyApp", "List failure", it) }
)
```

#### [Kotlin - Coroutines]

```kotlin
val secondBucket = StorageBucket.fromOutputs("secondBucket")
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .bucket(secondBucket)
    .build()

try {
    val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
    result.items.forEach {
        Log.i("MyAmplifyApp", "Item: $it")
    }
    Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
    Log.e("MyAmplifyApp", "List failure", error)
}
```

#### [RxJava]

```java      
StorageBucket secondBucket = StorageBucket.fromOutputs("secondBucket");
StoragePagedListOptions options = StoragePagedListOptions.builder()
        .setPageSize(1000)
        .bucket(secondBucket)
        .build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
        .subscribe(
            result -> {
                for (StorageItem item : result.getItems()) {
                    Log.i("MyAmplifyApp", "Item: " + item.getPath());
                }
                Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
            },
            error -> Log.e("MyAmplifyApp", "List failure", error);
        );
```

Alternatively, you can also pass in an object by specifying the bucket name and region from the console.

#### [Java]

```java
BucketInfo bucketInfo = new BucketInfo("second-bucket-name-from-console", "us-east-2");
StorageBucket secondBucket = StorageBucket.fromBucketInfo(bucketInfo);
StoragePagedListOptions options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .bucket(secondBucket)
    .build();

Amplify.Storage.list(
    StoragePath.fromString("public/photos/"),
    options,
    result -> {
        for (StorageItem item : result.getItems()) {
            Log.i("MyAmplifyApp", "Item: " + item.getPath());
        }
        Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
    },
    error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

#### [Kotlin - Callbacks]

```kotlin
val bucketInfo = BucketInfo("second-bucket-name-from-console", "us-east-2")
val secondBucket = StorageBucket.fromBucketInfo(bucketInfo)
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .bucket(secondBucket)
    .build()

Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
    { result ->
        result.items.forEach { item ->
            Log.i("MyAmplifyApp", "Item: ${item.path}")
        }
        Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
    },
    { Log.e("MyAmplifyApp", "List failure", it) }
)
```

#### [Kotlin - Coroutines]

```kotlin
val bucketInfo = BucketInfo("second-bucket-name-from-console", "us-east-2")
val secondBucket = StorageBucket.fromBucketInfo(bucketInfo)
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .bucket(secondBucket)
    .build()

try {
    val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
    result.items.forEach {
        Log.i("MyAmplifyApp", "Item: $it")
    }
    Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
    Log.e("MyAmplifyApp", "List failure", error)
}
```

#### [RxJava]

```java
BucketInfo bucketInfo = new BucketInfo("second-bucket-name-from-console", "us-east-2");
StorageBucket secondBucket = StorageBucket.fromBucketInfo(bucketInfo);
StoragePagedListOptions options = StoragePagedListOptions.builder()
        .setPageSize(1000)
        .bucket(secondBucket)
        .build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
        .subscribe(
            result -> {
                for (StorageItem item : result.getItems()) {
                    Log.i("MyAmplifyApp", "Item: " + item.getPath());
                }
                Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
            },
            error -> Log.e("MyAmplifyApp", "List failure", error);
        );
```

### Exclude results from nested subpaths

By default, the `list` API will return all objects contained within the given path, including objects inside nested subpaths.

For example, the previous `public/photos/` path would include these objects:

```bash
Path: public/photos/photo1.jpg
Path: public/photos/vacation/photo1.jpg
Path: public/photos/thumbnails/photo1.jpg
```

In order to exclude objects within the `vacation` and `thumbnails` subpaths, you can set the `subpathStrategy` option to `SubpathStrategy.Exclude()`:

#### [Java]

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .setSubpathStrategy(SubpathStrategy.Exclude())
    .build();

Amplify.Storage.list(
    StoragePath.fromString("public/photos/"),
    options,
    result -> {
        for (StorageItem item : result.getItems()) {
            Log.i("MyAmplifyApp", "Item: " + item.getPath());
        }
        Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
    },
    error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

#### [Kotlin - Callbacks]

```kotlin
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .setSubpathStrategy(SubpathStrategy.Exclude())
    .build()

Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
    { result ->
        result.items.forEach { item ->
            Log.i("MyAmplifyApp", "Item: ${item.path}")
        }
        Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
    },
    { Log.e("MyAmplifyApp", "List failure", it) }
)
```

#### [Kotlin - Coroutines]

```kotlin
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .setSubpathStrategy(SubpathStrategy.Exclude())
    .build()

try {
    val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
    result.items.forEach {
        Log.i("MyAmplifyApp", "Item: $it")
    }
    Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
    Log.e("MyAmplifyApp", "List failure", error)
}
```

#### [RxJava]

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
        .setPageSize(1000)
        .setSubpathStrategy(SubpathStrategy.Exclude())
        .build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
        .subscribe(
            result -> {
                for (StorageItem item : result.getItems()) {
                    Log.i("MyAmplifyApp", "Item: " + item.getPath());
                }
                Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
            },
            error -> Log.e("MyAmplifyApp", "List failure", error);
        );
```

The response will only include objects within the `public/photos/` path and will also provide a list of the excluded subpaths:

```bash
Path: public/photos/photo01.jpg
Subpath: public/photos/vacation/
Subpath: public/photos/thumbnails/
```

The default delimiter character is `"/"`, but this can be changed by supplying a custom delimiter:

#### [Java]

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .setSubpathStrategy(SubpathStrategy.Exclude("-"))
    .build();

Amplify.Storage.list(
    StoragePath.fromString("public/photos/"),
    options,
    result -> {
        for (StorageItem item : result.getItems()) {
            Log.i("MyAmplifyApp", "Item: " + item.getPath());
        }
        Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
    },
    error -> Log.e("MyAmplifyApp", "List failure", error);
);
```

#### [Kotlin - Callbacks]

```kotlin
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .setSubpathStrategy(SubpathStrategy.Exclude("-"))
    .build()

Amplify.Storage.list(StoragePath.fromString("public/photos/"), options,
    { result ->
        result.items.forEach { item ->
            Log.i("MyAmplifyApp", "Item: ${item.path}")
        }
        Log.i("MyAmplifyApp", "Next Token: ${result.nextToken}")
    },
    { Log.e("MyAmplifyApp", "List failure", it) }
)
```

#### [Kotlin - Coroutines]

```kotlin
val options = StoragePagedListOptions.builder()
    .setPageSize(1000)
    .setSubpathStrategy(SubpathStrategy.Exclude("-"))
    .build()

try {
    val result = Amplify.Storage.list(StoragePath.fromString("public/photos/"), options)
    result.items.forEach {
        Log.i("MyAmplifyApp", "Item: $it")
    }
    Log.i("MyAmplifyApp", "next token: ${result.nextToken}")
} catch (error: StorageException) {
    Log.e("MyAmplifyApp", "List failure", error)
}
```

#### [RxJava]

```java
StoragePagedListOptions options = StoragePagedListOptions.builder()
        .setPageSize(1000)
        .setSubpathStrategy(SubpathStrategy.Exclude("-"))
        .build();

RxAmplify.Storage.list(StoragePath.fromString("public/photos/"), options)
        .subscribe(
            result -> {
                for (StorageItem item : result.getItems()) {
                    Log.i("MyAmplifyApp", "Item: " + item.getPath());
                }
                Log.i("MyAmplifyApp", "Next Token: " + result.getNextToken());
            },
            error -> Log.e("MyAmplifyApp", "List failure", error);
        );
```

The response will only include objects within the `public/photos/` path not grouped by the delimiter `-`.

```bash
Path: public/photos/2023/photos01.jpg
Path: public/photos/2024/photos02.jpg
Subpath: public/photos/202-
```

### All `list` options

| Option | Type | Description |
| --- | --- | --- |
| subpathStrategy | SubpathStrategy | The strategy to use when listing contents from subpaths. |
| pageSize | int | Number between 1 and 1,000 that indicates the limit of how many entries to fetch when retrieving file lists from the server. |
| bucket | StorageBucket | The bucket in which the objects are stored. |
| nextToken | String | String indicating the page offset at which to resume a listing. |

If the `pageSize` is set lower than the total file size available, a single `list` call only returns a subset of all the files. To list all the files with multiple calls, the user can use the `nextToken` value from the previous response.
<!-- /Platform -->

<!-- Platform: swift -->
The following example lists all objects inside the `public/photos/` path:

#### [Async/Await]

```swift
let listResult = try await Amplify.Storage.list(
    path: .fromString("public/photos/")
)
listResult.items.forEach { item in
    print("Path: \(item.path)")
}
```

#### [Combine]

```swift
let sink = Amplify.Publisher.create {
    try await Amplify.Storage.list(
        path: .fromString("public/photos/")
    )
}.sink {
    if case let .failure(error) = $0 {
        print("Failed: \(error)")
    }
}
receiveValue: { listResult in
    listResult.items.forEach { item in
        print("Path: \(item.path)")
    }
}
```

<Callout>
Note the trailing slash `/` in the given path.

If you had used `public/photos` as path, it would also match against files like `public/photos01.jpg`.
</Callout>

### List files from a specified bucket

You can perform a list operation from a specific bucket by providing the `bucket` option.

#### [From Outputs]
You can use `.fromOutputs(name:)` to provide a string representing the target bucket's assigned name in the Amplify Backend.

```swift
let listResult = try await Amplify.Storage.list(
    path: .fromString("public/photos/"),
    options: .init(
        bucket: .fromOutputs(name: "secondBucket")
    )
)
```

#### [From Bucket Info]
You can also use `.fromBucketInfo(_:)` to provide a bucket name and region directly.

```swift
let listResult = try await Amplify.Storage.list(
    path: .fromString("public/photos/"),
    options: .init(
        bucket: .fromBucketInfo(.init(
            bucketName: "another-bucket-name",
            region: "another-bucket-region")
        )    
    )
)
```

### Exclude results from nested subpaths

By default, the `list` API will return all objects contained within the given path, including objects inside nested subpaths.

For example, the previous `public/photos/` path would include these objects:

```bash
Path: public/photos/photo1.jpg
Path: public/photos/vacation/photo1.jpg
Path: public/photos/thumbnails/photo1.jpg
```

In order to exclude objects within the `vacation` and `thumbnails` subpaths, you can set the `subpathStrategy` option to `.exclude`:

#### [Async/Await]

```swift
let listResult = try await Amplify.Storage.list(
    path: .fromString("public/photos/"),
    options: .init(
        subpathStrategy: .exclude
    )
)
listResult.items.forEach { item in
    print("Path: \(item.path)")
}
listResult.excludedSubpaths.forEach { subpath in
    print("Subpath: \(subpath)")
}
```

#### [Combine]

```swift
let sink = Amplify.Publisher.create {
    try await Amplify.Storage.list(
        path: .fromString("public/photos/"),
        options: .init(
            subpathStrategy: .exclude
        )
    )
}.sink {
    if case let .failure(error) = $0 {
        print("Failed: \(error)")
    }
}
receiveValue: { listResult in
    listResult.items.forEach { item in
        print("Path: \(item.path)")
    }
    listResult.excludedSubpaths.forEach { subpath in
        print("Subpath: \(subpath)")
    }
}
```

The response will only include objects within the `public/photos/` path and will also provide a list of the excluded subpaths:

```bash
Path: public/photos/photo01.jpg
Subpath: public/photos/vacation/
Subpath: public/photos/thumbnails/
```

The default delimiter character is `"/"`, but this can be changed by supplying a custom delimiter:

#### [Async/Await]

```swift
let listResult = try await Amplify.Storage.list(
    path: .fromString("public/photos-"),
    options: .init(
        subpathStrategy: .exclude(delimitedBy: "-")
    )
)
```

#### [Combine]

```swift
let sink = Amplify.Publisher.create {
    try await Amplify.Storage.list(
        path: .fromString("public/photos-"),
        options: .init(
            subpathStrategy: .exclude(delimitedBy: "-")
        )
    )
}.sink {
    if case let .failure(error) = $0 {
        print("Failed: \(error)")
    }
}
receiveValue: { listResult in
    // ...
}
```

### All `list` options

| Option | Type | Description |
| --- | --- | --- |
| subpathStrategy | SubpathStrategy | The strategy to use when listing contents from subpaths |
| pageSize | UInt | Number between 1 and 1,000 that indicates the limit of how many entries to fetch when retrieving file lists from the server |
| bucket | StorageBucket | The bucket in which the objects are stored |
| nextToken | String | String indicating the page offset at which to resume a listing. |

If the `pageSize` is set lower than the total file size available, a single `list` call only returns a subset of all the files. To list all the files with multiple calls, the user can use the `nextToken` value from the previous response.
<!-- /Platform -->

<!-- Platform: flutter -->
This will list all files located under path `album` that:

- have `private` access level
- are in the root of `album/` (the result doesn't include files under any sub path)

```dart
Future<void> listAlbum() async {
  try {
    String? nextToken;
    bool hasNextPage;
    do {
      final result = await Amplify.Storage.list(
        path: const StoragePath.fromString('public/album/'),
        options: StorageListOptions(
          pageSize: 50,
          nextToken: nextToken,
          pluginOptions: const S3ListPluginOptions(
            excludeSubPaths: true,
          ),
        ),
      ).result;
      safePrint('Listed items: ${result.items}');
      nextToken = result.nextToken;
      hasNextPage = result.hasNextPage;
    } while (hasNextPage);
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}
```

Pagination is enabled by default. The default `pageSize` is `1000` if it is not set in the `StorageListOptions`.

### List all files without pagination

You can also list all files under a given path without pagination by using the `pluginOptions` and `S3ListPluginOptions.listAll()` constructor.

This will list all public files (i.e. those with `guest` access level):

```dart

Future<void> listAllUnderPublicPath() async {
  try {
    final result = await Amplify.Storage.list(
      path: const StoragePath.fromString('public/'),
      options: const StorageListOptions(
        pluginOptions: S3ListPluginOptions.listAll(),
      ),
    ).result;
    safePrint('Listed items: ${result.items}');
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}

```
<!-- Platform: flutter -->
### List files from a specified bucket
You can also perform a `list` operation to a specific bucket by providing the `bucket` option. You can pass in a `StorageBucket` object representing the target bucket from the name defined in the Amplify Backend.

```dart
final result = await Amplify.Storage.list(
  path: const StoragePath.fromString('path/to/dir'),
  options: StorageListOptions(
    // highlight-start
    // Specify a target bucket using name assigned in Amplify Backend
    bucket: StorageBucket.fromOutputs('secondBucket'),
    // highlight-end
  ),
).result;
```
Alternatively, you can also pass in an object by specifying the bucket name and region from the console.

```dart
final result = await Amplify.Storage.list(
  path: const StoragePath.fromString('path/to/dir'),
  options: StorageListOptions(
    // highlight-start
    // Alternatively, provide bucket name from console and associated region
   bucket: StorageBucket.fromBucketInfo(
        BucketInfo(
          bucketName: 'second-bucket-name-from-console',
          region: 'us-east-2',
        ),
      ),
      // highlight-end
  ),
).result;
```
<!-- /Platform -->

### More `list` options

| Option | Type | Description |
| --- | --- | --- |
| bucket | StorageBucket | The target bucket from the assigned name in the Amplify Backend or from the bucket name and region in the console<br/><br/>Defaults to the default bucket and region from the Amplify configuration if this option is not provided.<br/><br/>Read more at [Configure additional storage buckets](/[platform]/build-a-backend/storage/set-up-storage/#configure-additional-storage-buckets) |
| excludeSubPaths | boolean | Whether to exclude objects under the sub paths of the path to list. Defaults to false. |
| delimiter | String | The delimiter to use when evaluating sub paths. If excludeSubPaths is false, this value has no impact on behavior. |
<!-- /Platform -->

<!-- Platform: react, angular, javascript, vue, nextjs, react-native -->
## Get File Properties

You can also view the properties of an individual file.

```javascript
import { getProperties } from 'aws-amplify/storage';

try {
  const result = await getProperties({
    path: 'album/2024/1.jpg',
    // Alternatively, path: ({ identityId }) => `album/${identityId}/1.jpg`
    options: {
      // Specify a target bucket using name assigned in Amplify Backend
      bucket: 'assignedNameInAmplifyBackend'
    }
  });
  console.log('File Properties ', result);
} catch (error) {
  console.log('Error ', error);
}
```

The properties and metadata will look similar to the below example

```js
{
  path: "album/2024/1.jpg",
  contentType: "image/jpeg",
  contentLength: 6873,
  eTag: "\"56b32cf4779ff6ca3ba3f2d455fa56a7\"",
  lastModified: Wed Apr 19 2023 14:20:55 GMT-0700 (Pacific Daylight Time) {},
  metadata: { owner: 'aws' }
}
```

### More `getProperties` options

Option | Type | Default | Description |
| -- | -- | -- | ----------- |
| bucket | string \| <br />\{ bucketName: string;<br/> region: string; \} | Default bucket and region from Amplify configuration | A string representing the target bucket's assigned name in Amplify Backend or an object specifying the bucket name and region from the console.<br/><br/>Read more at [Configure additional storage buckets](/[platform]/build-a-backend/storage/set-up-storage/#configure-additional-storage-buckets) |
| useAccelerateEndpoint | boolean | false | Whether to use accelerate endpoint. | [Transfer Acceleration](/[platform]/build-a-backend/storage/extend-s3-resources/#example---enable-transfer-acceleration) |

<Callout>

To get the metadata in result for all APIs you have to configure user defined metadata in CORS.

Learn more about how to setup an appropriate [CORS Policy](/[platform]/build-a-backend/storage/extend-s3-resources/#for-manually-configured-s3-resources).

</Callout>
<!-- /Platform -->

<!-- Platform: flutter -->
## Get File Properties

You can also view properties of an individual file.

```dart
Future<void> getFileProperties() async {
  try {
    final result = await Amplify.Storage.getProperties(
      path: const StoragePath.fromString('example.txt'),
    ).result;
    safePrint('File size: ${result.storageItem.size}');
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}
```

As well as specify a bucket to target to view properties of a file

```dart
Future<void> getFileProperties() async {
  try {
    final result = await Amplify.Storage.getProperties(
      path: const StoragePath.fromString('example.txt'),
      options: StorageGetPropertiesOptions(
        StorageBucket.fromOutputs('secondBucket'),
      ),
      // Alternatively, provide bucket name from console and associated region
      /*
      options: StorageGetPropertiesOptions( 
        bucket: StorageBucket.fromBucketInfo(
          BucketInfo(
            bucketName: 'second-bucket-name-from-console',
            region: 'us-east-2',
          ),
        ),
      ),
      */
    ).result;
    safePrint('File size: ${result.storageItem.size}');
  } on StorageException catch (e) {
    safePrint(e.message);
  }
}
```

<Callout>

To get the metadata in result for all APIs when building against a web target, you have to configure user defined metadata in CORS.

Learn more about how to setup an appropriate [CORS Policy](/[platform]/build-a-backend/storage/extend-s3-resources/#for-manually-configured-s3-resources).

</Callout>
<!-- /Platform -->
